Skip to Content
Technical Articles

Display Standard text using CDS annotation @ObjectModel.virtualElement in Gateway Service (Odata) or Fiori


Often we come across scenario where we need to display document/item text, which are stored in SAP as standard text. This blogs explains how standard text can be displayed in Gateway Service (Odata) or Fiori using CDS annotation @ObjectModel.virtualElement.

What Are Virtual Elements, and Why Do I Need Them?

For some business use cases, it may be necessary to add new fields to the data model (CDS/table) of an application and to calculate their values using ABAP programming (like FM, methods). Virtual elements come into play if these fields are not provided as part of the original persistence data model or cannot be easily integrated (derived) in CDS so that their values can be calculated directly on SAP HANA.

Virtual elements represent transient fields in business applications. They are defined at the level of CDS consumption views as additional elements within the SELECT list using specific @DataModel annotations. However, the calculation or further processing of their values is carried out by means of ABAP classes that implement the specific code exit interfaces provided for this purpose.

It can be conceptualize as CDS field exit.

Please check Virtual Element for more details.


Example tested on system: SAP S/4 HANA 1909( AS ABAP 754)

In below example, I will derive Purchase Order Item text which is stored as Standard text.

  • Create CDS & publish it as Odata service using Auto-exposure

     CDS Source Code

@AbapCatalog.sqlViewName: 'ZVPOITEXT'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Purchase Order Item Standard Text in CDS'
@OData: { publish: true }            --Publish CDS as OData Service

define view ZPurchaseOrderItemText
  as select from I_PurchaseOrderItem --Data Source: Standard CDS(Purchase Document Line items)
  key PurchaseOrder,                              --Purchase Document number
  key PurchaseOrderItem,                          --Purchase Document Item number
      @ObjectModel.virtualElement: true
      @ObjectModel.virtualElementCalculatedBy: 'ZCL_PO_ITEM_TEXT'
      cast( ''  as abap.char(255)) as item_text1, ---field limited to maximum 255 characters for text
      @ObjectModel.virtualElement: true
      @ObjectModel.virtualElementCalculatedBy: 'ZCL_PO_ITEM_TEXT'
      cast( ''  as abap.char(255)) as item_text2  ---field limited to maximum 255 characters for text
  • Register & activate the OData service in T-code: /N/IWFND/MAINT_SERVICE

      Auto-generated CDS based OData service-naming convention: CDS entity name + ‘_CDS’

Service registered & activated.

Check CDS source code, new icon will be displayed after successful service registration as below:

  • Create class & implement interface IF_SADL_EXIT_CALC_ELEMENT_READ. This interface has 2 methods as below:

       Implement the method calculate & add below logic to fetch PO Item text

METHOD if_sadl_exit_calc_element_read~calculate.
        DATA : lt_poitem    TYPE STANDARD TABLE OF zvpoitext WITH DEFAULT KEY,
               lt_lines     TYPE STANDARD TABLE OF tline,
               lv_long_text TYPE string.

        lt_poitem = CORRESPONDING #( it_original_data ).

        LOOP AT lt_poitem ASSIGNING FIELD-SYMBOL(<ls_poitem>).
*--preapre PO item text name
          DATA(lv_name) = CONV tdobname( <ls_poitem>-purchaseorder && <ls_poitem>-purchaseorderitem ).
              client                  = sy-mandt
              id                      = 'F01'
              language                = sy-langu
              name                    = lv_name
              object                  = 'EKPO'
              lines                   = lt_lines
              id                      = 1
              language                = 2
              name                    = 3
              not_found               = 4
              object                  = 5
              reference_check         = 6
              wrong_access_to_archive = 7
              OTHERS                  = 8.
          IF sy-subrc IS INITIAL.
            LOOP AT lt_lines ASSIGNING FIELD-SYMBOL(<ls_lines>).
              lv_long_text =  lv_long_text && <ls_lines>-tdline .
*--split text into below field with maximum 255 characters
            <ls_poitem>-item_text1 = lv_long_text+0(255).
            <ls_poitem>-item_text2 = lv_long_text+255(255).
            CLEAR lv_long_text.
*--return derived text
          ct_calculated_data = CORRESPONDING #( lt_poitem ).
*--catch exception to avoid short dump
      CATCH cx_root INTO DATA(lo_err).
        DATA(lv_msg) = lo_err->get_text(  ).

PO item standard text details:

ID: F01

Name: Purchase Document + Item Number

Object: EKPO

  • Test gateway service

Standard text fetched & displayed in filed item_text1 & item_text2 as below:


The service can further be consumed in Fiori .



You must be Logged on to comment or reply to a post.