Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
abhishekd
Advisor
Advisor
This Blog will be continuation of the 1st part of the blog where I explained how we can generate Fragmented Forms from Fiori List report using SEGW (OData) Project.

Part-1 - Preview/Download Fragmented Forms From Fiori List Report

In this part of the blog, I will be explaining how we can switch/ convert SEGW project to Unmanaged query (Custom CDS view) to make the solution as cloud ready.

 

Technical details


Backend API (Unmanaged Query)

For Creating the Form API in backend, we will use custom entity (ZCUSTOM_FORMAPI) with billing doc as parameter which will be used to get the billing document of the selected line.

Custom CDS entity will have one below field.

  • Stream_data - This field will hold the data for the PDF file and has a custom data type of RAWSTRING with length 0.



Note:  We cannot use RAWSTRING domain directly so we have to create a custom data element with data type as RAWSTRING and Length as ‘0’. This is important as length being ‘0’ would indicate that the RAWSTRING has No length restriction and can accommodate file of larger size.


Custom CDS View


The above custom CDS entity will not have any select rather the data will be fetched at runtime from the class defined using annotation @ObjectModel.query.implementedBy

It requires an ABAP class that implements the select method of the interface IF_RAP_QUERY_PROVIDER.

 

Query Implementation Class Logic

  1. Code first check if data is being requested or not (using io request->requested() )

  2. Using method io_request->get_parameters( ) to get the selected billing document sent from UI

  3. Create keys for content and master form.

  4. Call the get_document() API and send the response back to UI.


CLASS zcl_otc_print DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .

PUBLIC SECTION.

INTERFACES if_rap_query_provider .
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.



CLASS ZCL_OTC_PRINT IMPLEMENTATION.


METHOD if_rap_query_provider~select.

DATA: lt_tab TYPE TABLE OF ZCUSTOM_FORMAPI.
DATA: lt_master_keys TYPE cl_somu_form_services=>ty_gt_key.
DATA: lv_content TYPE xstring.
DATA: lo_cl_somu_form_services TYPE REF TO cl_somu_form_services,
lt_keys TYPE cl_somu_form_services=>ty_gt_key.


TRY.
** requested data
IF io_request->is_data_requested( ).
**paging
DATA(lv_offset) = io_request->get_paging( )->get_offset( ).
DATA(lv_page_size) = io_request->get_paging( )->get_page_size( ).
DATA(lv_max_rows) = COND #( WHEN lv_page_size = if_rap_query_paging=>page_size_unlimited
THEN 0 ELSE lv_page_size ) .

** Get the selected billing document from UI
TRY.
DATA(lt_parameters) = io_request->get_parameters( ).
** P_BILLINGDOC is the parameter of custom entity
DATA(lv_billdoc) = VALUE #( lt_parameters[ parameter_name = 'P_BILLINGDOC' ]-value OPTIONAL ).

* " --------------------------- Key Value for the Billing Doc content form --------

lt_keys = VALUE #( ( name = 'BillingDocument' value = lv_billdoc )
( name = 'SenderCountry' value = 'DE' )
( name = 'Language'(040) value = 'E' ) ) .


* " --------------------------- Key Value for the master form template ---------------------------

lt_master_keys = VALUE #( ( name = 'PrintFormDerivationRule' value = 'ZINVOICE_FORM' )
( name = 'WatermarkText' value = space )
( name = 'LocaleCountry' value = 'DE')
( name = 'LocaleLanguage' value = 'E' )
( name = 'OutputControlApplicationObjectType' value = 'BILLING_DOCUMENT' )
( name = 'OutputControlApplicationObject' value = lv_billdoc )
( name = 'OutputRequestItem' value = '000001' )
( name = 'OutputDocumentType' value = 'BILLING_DOCUMENT' )
( name = 'Recipient'(041) value = '00000001003' )
( name = 'RecipientRole' value = 'RE' )
( name = 'SenderCountry' value = 'DE' )
( name = 'ReceiverPartnerNumber' value = '00000001003' ) ).
lo_cl_somu_form_services = cl_somu_form_services=>get_instance( ).

TRY.
* " --------------------------- Call GET_DOCUMENT API ---------------------------
lo_cl_somu_form_services->get_document( EXPORTING iv_master_form_name = 'ZZ1_OTC_INVOICE_MASTER_A4'
iv_form_name = 'ZZ1_OTC_INVOICE_OUTPUT'
it_key = lt_keys
it_master_key = lt_master_keys
iv_form_language = 'E'
iv_form_country = 'DE'
IMPORTING ev_content = lv_content
).
CATCH cx_somu_error INTO DATA(lv_formerror).

ENDTRY.
lt_tab = VALUE #( ( stream_data = lv_content
) ).
io_response->set_total_number_of_records( 1 ).
* " -------------- Send the response back to UI------------
io_response->set_data( lt_tab ).

CATCH cx_rap_query_filter_no_range INTO DATA(lv_range).
DATA(lv_msg) = lv_range->get_text( ).
ENDTRY.


ENDIF.
CATCH cx_rap_query_provider.
ENDTRY.
ENDMETHOD.
ENDCLASS.

 

Create service definition.


Service Definition


 

Create service binding for the above service and publish it.

 


Service binding


 

Frontend

Define additional data source for the backend service (Custom CDS entity service binding) which we have created, under the “dataSources” section of manifest file for fetching PDF data.


Data Source


 

This OData data source should be mapped to a UI5 model in manifest file under “models” section.


 


Model


 

Controller File Logic -

  1. onPrintPreview method will be called when user select a line and clicks on Print Preview button.

  2. Create object of PDF Viewer and add it to current view.

  3. Open the busy indicator and call the getPDFData() method.

  4. In getPDFData() method, get call was made to get the PDF data from ZAPI_FORM API by passing billing document as a parameter to API.

  5. Promise data (PDF data) will be returned which will be decoded using atob()

  6. Create a Blob (binary large object) using byte array (decoded content) and set the type as  'application/pdf'

  7. Create the URL by passing the Blob as parameter to createObjectURL method and set it to the source of PDF viewer


 getPDFData: function () {

// get the Model reference
var oModel = this.getView().getModel("oFormModel");

//get selected line index
var selectedIndex = this.getView().byId('xx.sellbuybackreport::sap.suite.ui.generic.template.ListReport.view.ListReport::ZC_OTC_SELLBUYBACK_DETAILS--GridTable')
.getAggregation("plugins")[0].getSelectedIndex() ;

// get billing document from selected index
var vSelectedBillDoc = this.getView().byId('xx.sellbuybackreport::sap.suite.ui.generic.template.ListReport.view.ListReport::ZC_OTC_SELLBUYBACK_DETAILS--GridTable').
getContextByIndex(selectedIndex).getProperty('CorrectBillingDocZG2');

return new Promise((resolve,reject)=>{

// Perform Read operation and pass billingdoc as parameter to URL
oModel.read( "/ZCUSTOM_FORMAPI(p_billingdoc='" + vSelectedBillDoc + "')/Set" ,
{
success: function (oData,oResponse){
resolve(oData);
},
error: function (oError) {
reject(oError);
}
});
})
},
onPrintPreview: async function(oEvent) {

var opdfViewer = new PDFViewer();
this.getView().addDependent(opdfViewer);
var oBusyDialog = new sap.m.BusyDialog({
title: 'Generating Form...'
} );
oBusyDialog.open();

// Get the PDF data
var vPDF = await this.getPDFData();

let base64EncodedPDF = vPDF.results[0].stream_data;

let decodedPdfContent = atob(base64EncodedPDF);
let byteArray = new Uint8Array(decodedPdfContent.length);
for (var i = 0; i < decodedPdfContent.length; i++) {
byteArray[i] = decodedPdfContent.charCodeAt(i);
}
var blob = new Blob([byteArray.buffer], {
type: 'application/pdf'
});
var pdfurl = URL.createObjectURL(blob);
jQuery.sap.addUrlWhitelist("blob"); // register blob url as whitelist
opdfViewer.setSource(pdfurl);
opdfViewer.setVisible(true);

opdfViewer.setTitle("Billing Document ");
console.log('Reached to PDF')
opdfViewer.open();
oBusyDialog.close();


}

 

Working of Application --


User selects a line and click on Print Preview


 


Below call was made to the backend API along with selected billing documented in parameter field



 


Print Preview


That's the end of requirement. I appreciate that you have gone through the concept. This was one such requirement where extension is required on top of Fiori list report.

Thanks
13 Comments
former_member849676
Discoverer
This is exactly the same blog which i was searching for. Thanks! Abhishek 🙂

 
DiegoValdivia
Participant
This was a great post. Thanks Abhishek!
ManjunathAdva
Product and Topic Expert
Product and Topic Expert
Hi Abhishek,

Thanks for writing these blogs, it is very helpful.

 
sinhsr007
Discoverer
Precisely explained blog.
NishuBajpai
Associate
Associate
Hi Abhishek,

Thank you for the blog... This has saved us from lot of RnD. Just one learning would like to share here. For our case PDFViewer.Open was not opening the PDF Document and to handle this we have added below command for Generated BLOB:

JQuery.sap.addURLWhitelist("blob")

Hope this will help people struggling with same issue.

 
j_pavan_kumar
Product and Topic Expert
Product and Topic Expert
0 Kudos
Hi Abhishek,

Nice blog 🙂 .

I have few observations from the blogpost:

  • Instead of creating a custom entity and another service just to retrieve the attachment data, you can use the same "print preview" instance action to fetch the attachment data (XSTRING and MIME type) and send the result in the abstract entity so that this overhead of creating the custom entity can be reduced.

  • The business object can hold attachments of different formats. Do you know about the attachment service reusable component which does the job for handling various formats in the application. Please refer the below blogpost for more details.                                                  https://blogs.sap.com/2019/12/16/attachment-service-to-your-rescue-in-s4hana-fiori-elements-using-re...


Thanks,

Pavan
abhishekd
Advisor
Advisor
0 Kudos
Thanks Nishu!!
abhishekd
Advisor
Advisor
0 Kudos

Thanks Pavan , will surely check this approach as well ..

abhishekd
Advisor
Advisor
0 Kudos
Thanks !!
abhishekd
Advisor
Advisor
0 Kudos
Thanks Manjunath !!
abhishekd
Advisor
Advisor
0 Kudos
Thanks Satyam!!
abhishekd
Advisor
Advisor
0 Kudos
Great Anjali !!
vominhtam
Participant
0 Kudos
Hi abhishekd,

Blogs are very helpful.

I want to redesign the form, where can I get the form? At the Print Preview step.

Thank.

Tâm Võ.