CDS - Virtual fields
This article is about virtual fields in Core Data Services and how you can subsequently deliver such complex data.
Table of contents
Article update: Since release 7.57 (S/4 HANA 2022), DEFINE VIEW is marked as obsolete, you should use DEFINE VIEW ENTITY instead. These may differ from the examples in some places. You can find more information about the new views in this article.
Today we will show you how to insert virtual elements into CDS Views and how to fill them with data. We will also go into the special features that you should consider.
General
Virtual items, as the name suggests, are not persistent data from the database, but are created to retrieve the data. This goes hand in hand with some special features that you should consider when using them:
- The data is filled using the SADL class, so it is not possible to display the data using Data Preview, the field there remains empty.
- In terms of performance, the virtual element is unsuitable for selection and filtering via the service or the Fiori interface.
Virtual elements
To do this, we create a core data service and create a virtual column "PricePerUnit". The column also needs an annotation "@ObjectModel.virtualElementCalculatedBy" so that it is announced via which class the content is generated.
@AbapCatalog.sqlViewName: 'ZBSIDMOPRIPERUNI'
@EndUserText.label: 'Exit in CDS'
define view ZBS_C_DmoPricePerUnit
as select from ZBS_I_DmoPosition
{
key DocumentNumber,
key PositionNumber,
_Material.MaterialName,
PositionQuantity,
PositionPrice,
PositionCurrency,
@ObjectModel.virtualElementCalculatedBy: 'ABAP:ZCL_BS_DEMO_CDS_EXIT'
cast( 0 as abap.curr(15,2) ) as PricePerUnit
}
Class
You then have to implement the exit to fill the field with data. To do this, create the class with the previously defined name and implement the "if_sadl_exit_calc_element_read" interface.
CLASS zcl_bs_demo_cds_exit DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_sadl_exit_calc_element_read.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_bs_demo_cds_exit IMPLEMENTATION.
METHOD if_sadl_exit_calc_element_read~calculate.
DATA:
lt_view_data TYPE STANDARD TABLE OF ZBS_C_DmoPricePerUnit WITH EMPTY KEY.
lt_view_data = CORRESPONDING #( it_original_data ).
LOOP AT lt_view_data REFERENCE INTO DATA(lr_view_data).
lr_view_data->PricePerUnit = lr_view_data->PositionPrice / lr_view_data->PositionQuantity.
ENDLOOP.
ct_calculated_data = CORRESPONDING #( lt_view_data ).
ENDMETHOD.
METHOD if_sadl_exit_calc_element_read~get_calculation_info.
ENDMETHOD.
ENDCLASS.
The interface provides two methods. In the first step, the "GET_CALCULATE_INFO" method is called, where the fields and information to be determined are transferred again. In the "CALCULATE" method you then calculate or fill in the fields. However, the changing parameter only contains the elements to be calculated.
Display
If we now look at the data via Data Preview in Eclipse, then we get an empty column. The SADL exit is not run through with this form of display and the data is therefore not enriched.
If we now build an app via RAP to view the data in an OData in a Fiori Elements app, the corresponding exit is called, the data is now also filled and displayed. The CDS view can also simply be published as an OData service; the display in the browser would then work just as well. The annotation "@OData.publish: true" can also be used for this:
Conclusion
If you ever have to derive complex data and you cannot map it as a CDS view, then you also have the option of reading additional data and integrating complex logic into the view. However, you must note that the logic then only works in the remote scenario.