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: 
333

Use Case:

When the user clicks the "CSV" button, the application will fetch the accounting document details and it will then prepare a CSV file. This CSV file will then be downloaded and stored in the local filesystem on the user's device.

The screenshot below shows the CAP application UI, which includes a custom button to trigger CSV generation and download.

SumithraSudharsanam_0-1719825684065.png

The downloaded CSV looks like the screenshot below:

SumithraSudharsanam_1-1719825684070.png

Implementation Steps:

  • Define a Virtual field in service
  • Handler logic to generate and download csv
    • Importing necessary modules
    • Implementing the Read Handler
    • Preparing the JSON Content
    • Converting the JSON to CSV
    • Converting CSV data to buffer to download
  • Converting “Open file” link to a button in the UI

Define a Virtual field in service: Define a virtual field at the service level with type “LargeBinary” and media type “application/csv”.

entity Documents {
    key ID                  : UUID;
     name                : String;
        virtual null as csv : LargeBinary @Core.MediaType: 'application/csv',
}

 

This will automatically generate a hyperlink labelled “Open File” in the UI as shown in the screenshot below.

SumithraSudharsanam_2-1719825684073.png

Handler logic to generate and download csv:

To download an accounting document in CSV format, first, retrieve the accounting Document with Book and accounting Principle  details for the specified document ID using a database transaction. Then, convert the csv data to a buffer. Finally, set the file name based on the accounting document ID and specify the content type as CSV.

Importing Necessary Modules

To handle the conversion and streaming of the CSV content, you'll require the Buffer and Readable modules from Node.js and json2csv library to convert the Json data to csv format. Import these modules into your project with the following code:

import { Buffer } from "buffer";
import { Readable } from "stream";
import { json2csv } from "json-2-csv";

Add the “json2csv” library through package.json

  "dependencies": {
    "json-2-csv": "^5.5.1",

Implementing the Read Handler:

In the Read handler of the entity, verify if the URL path includes "csv". (name of the virtual field defined in your entity). If you have named the virtual field differently, ensure to check for that specific name in the URL.

  virtual null                as csv                  : LargeBinary @Core.MediaType: 'application/csv',

If the URL path contains the specified virtual field name(url.includes(“csv”)), proceed to generate the CSV content. Convert this CSV content into buffer data, push the buffered data into a Readable stream, and return it. Make sure to include the media content type and the disposition filename in the response.

Example:

/dch/ui/accounting/documents/Documents(${object.ID})/csv

Preparing the JSON content :

Construct the JSON content with the retrieved data from the database.

let documentOutputValue: RetrieveDocumentDetails = {

      "Entity Type": EntityTypeCodes.ACCOUNTING_DOCUMENT,
      ID: documentsHeaderData.displayId.toString(),
      Company: companyData.name,
      "Accounting Principle": accountingPrincipleData.code,
      "Key Date": documentsHeaderData.CutOffDate,
      "Created On": documentsHeaderData.createdAt,
      "Created By": documentsHeaderData.createdBy,
      "Item ID": "",
      "Item Type": "",
      "Amount (Position Currency)": "",
      "Position Currency": "",
      "Amount (Local Currency)": "",
      "Local Currency": "",
      Text: "SAP Digital Currency Hub"
    };

Converting the JSON to CSV:

Convert the JSON content to CSV format by passing the JSON data to the json2csv library function, enabling the download of the data as a file.

  //Prepare csv output file
          const csvOptions = {
            delimiter: {
              wrap: '"',
              field: ";", // specify the delimiter here
              eol: "\n"
            }
          };
          const csvOutput = json2csv(documentOutput, csvOptions);

Converting CSV data to buffer to download:

Adding the CSV data to a buffer is necessary because buffers handle raw binary data, which is useful for file operations such as downloading. Converting the CSV data to a buffer ensures that the data is correctly encoded and can be managed efficiently for creating the downloadable file. This step is crucial for maintaining data integrity during the download process.

        BufferData = Buffer.from(csvOutput, "utf8");
          fileName = `AccountingDocument${documentsHeaderData.displayId}.csv`;
          contentType = "application/csv";
          return this.returnBufferContents(BufferData, fileName, contentType);

Converting “Open File” link to a button in the UI:

Define a UI Fragment that contains a button with the handler in app/webapp/ext/fragment section.

<core:FragmentDefinition xmlns:core="sap.ui.core" xmlns="sap.m">
    <Button
        core:require="{ handler: 'sap/erp4sme/c4b/accounting/documents/ext/fragment/ActionCsvDownload'}"
        text="CSV" press="handler.onPress" />
</core:FragmentDefinition>

Create a handler for the button that, when pressed, displays a toast message saying "DownloadingCSV" and then redirects the browser to the CSV URL.

sap.ui.define([
    "sap/m/MessageToast"
], function (MessageToast) {
    'use strict';
    return {
        onPress: function (oEvent) {
            const view = this.editFlow.getView();
            const i18nModelBundle = view.getModel("i18n").getResourceBundle();
            MessageToast.show(i18nModelBundle.getText("DownloadingCSV"));
            const object = oEvent.getSource().getBindingContext().getObject();
            sap.m.URLHelper.redirect(`/dch/ui/accounting/documents/Documents(${object.ID})/csv`, true);
        }
    };
});

Add the fragment in the columns section in manifest.json.

                  "ActionCsvDownload": {
                                            "header": "{i18n>downloadcsv}",
                                            "position": {
                                                "anchor": "DataFieldForAction::DocumentsUiService.unconfirmPosting",
                                                "placement": "After"
                                            },
                                            "template": "sap.erp4sme.c4b.accounting.documents.ext.fragment.ActionCsvDownload",
                                            "horizontalAlign": "Center",
                                            "width": "5em"
                                        }