Skip to Content
Technical Articles
Author's profile photo Ankit Sinha

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

Overview

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
@VDM.viewType: #CONSUMPTION
@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.
    TRY.
        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 ).
          CALL FUNCTION 'READ_TEXT'
            EXPORTING
              client                  = sy-mandt
              id                      = 'F01'
              language                = sy-langu
              name                    = lv_name
              object                  = 'EKPO'
            TABLES
              lines                   = lt_lines
            EXCEPTIONS
              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 .
            ENDLOOP.
*--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.
          ENDIF.
*--return derived text
          ct_calculated_data = CORRESPONDING #( lt_poitem ).
        ENDLOOP.
*--catch exception to avoid short dump
      CATCH cx_root INTO DATA(lo_err).
        DATA(lv_msg) = lo_err->get_text(  ).
    ENDTRY.
  ENDMETHOD.

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 .

 

 

Assigned Tags

      6 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Andrew Fordham
      Andrew Fordham

      Hi Ankit,

      Great blog!  As an aside, the S/4HANA system I'm working on allows fields of up to 1333 characters in length in CDS views, so you can fit a lot more of the standard text into a single field.

      Regards,

      Andrew

      Author's profile photo Ankit Sinha
      Ankit Sinha
      Blog Post Author

      Hello Andrew,

       

      Thanks! Yes we can allow field up to 1333 characters(based on data type). However I just tried to show split into different fields in the example.

      https://help.sap.com/doc/abapdocu_751_index_htm/7.51/en-us/abenddic_builtin_types.htm

       

      Regards

      Ankit

       

      Author's profile photo Marçal Oliveras
      Marçal Oliveras

      Good blog! I thought about this but I never implemented it, at the end it was not needed in my project.

      SAP should provide a standard option for this…

      Author's profile photo Gaspar Zoltan Erdelyi
      Gaspar Zoltan Erdelyi

      The exit implementation could be optimized for better performance using function module READ_TEXT_TABLE. Calling READ_TEXT in a LOOP will result in many small queries to the database.
      See SAP Note 2261311 for details.

      Author's profile photo Shai Sinai
      Shai Sinai

      Surprisingly, a very similar post was published just 4 days earlier:

      Read Long Texts using ‘READ_TEXT’ in CDS Views

      Author's profile photo Abhishek Sharma
      Abhishek Sharma

      Hi Ankit Sinha

      Thanks much for post...

       

      Thanks-

      Abhishek