Creating PDF documents in OpenUI5 (Fiori) Apps

This article is a repost of Michael’s blog post on https://mrentzsch.wordpress.com/2015/10/12/creating-pdf-documents-in-openui5-apps/

I have been a fan of OpenUI5 (or UI5 in general) ever since my first encounters with it in late 2013. Thus, I have been trying to do some of my work using OpenUI5, and, hence, I have decided to write a few blog posts about UI5 and about how certain things can be achieved. I have mainly been focusing on new apps for our company and myself, since most of our customers have not yet switched to using mobile enabled applications heavily or rather rely on the existing apps from SAP itself. I usually have a PHP-based back-end using JSON as data model provider, since a full SAP stack is an overkill in most cases.

When implementing business apps, creating PDF reports/documents that can be printed, sent via email or stored in an electronic archive often is a required feature. This can be achieved with two different approaches.

  1. It is possible to create the PDF using JavaScript libraries right on the (mobile) device. A common library for generating PDFs in JavaScript is jsPDF. This approach doesn’t require extra communication with the back-end or any back-end at all. On the downside, jsPDF doesn’t seem to be very robust when working with images. Thus, this approach is mainly fitting for small apps with simple output.
  2. The second option is producing the PDF document on the back-end. For PHP-driven services, fpdf is a very good tool for that. Just like jsPDF, fpdf is free software. In my tests, it proved much more reliable when producing complex output using images etc. For this approach, a new script/service has to be called. I found it to be a convenient solution to pass the required data (from the UI5 data model) as a JSON string (JSON.stringify) to the PHP service.

Below, you will find an example for generating PDFs directly on the mobile or desktop device using JavaScript and jsPDF and for creating the documents in the back-end with PDF and fpdf.

jsPDF: Document generation in the (mobile) app

Let us create a small app with input fields and a button for generating a PDF document. The PDF doc will contain the input value to show you, how you can connect your app data to the output process.

The UI5 coding for our apps looks like this:

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv='X-UA-Compatible' content='IE=edge' />
    <meta http-equiv='Content-Type' content='text/html;charset=UTF-8'/>
     
    <script id='sap-ui-bootstrap' type='text/javascript' src='https://openui5.hana.ondemand.com/resources/sap-ui-core.js' data-sap-ui-theme='sap_bluecrystal' data-sap-ui-libs='sap.m,sap.ui.commons'></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.1.135/jspdf.min.js"></script>
    <script>      
        var oModel = new sap.ui.model.json.JSONModel({ name: "Name", age: 30 });
        var p = new sap.m.Page( {
          title: "Generate PDF",
          content: [
            new sap.m.Label({ text: "Name:" }),
            new sap.m.Input({ value: "{/name}" } ),
            new sap.m.Label({ text: "Age:" }),
            new sap.m.Input({ value: "{/age}" } ),
            new sap.m.Button({ text: "Generate PDF", press: function(evt) {
              var n = evt.getSource().getModel().getProperty("/name");
              var a = evt.getSource().getModel().getProperty("/age");
               
              var doc = new jsPDF();
              doc.text(20, 20, "This is " + n);
              doc.text(20, 30, "She/he is " + a + " years old.");
              doc.save('sheet.pdf');
            }})
          ]
        } );
       
      var app = new sap.m.App({ pages: [ p ] }).placeAt("content");
      app.setModel(oModel);
    </script>
     
    </head>
    <body class='sapUiBody'>
      <div id='content'></div>
    </body>
</html>

As you can see, pushing the button “Generate PDF” will trigger the document output directly in the app. Therefore, a new object of type jsPDF has to be instantiated providing methods for adding content to the PDF document. jsPDF comes with a lot of examples showing you how to create bigger and more complex documents.

You can give the app a try on jsBin.

fpdf: Document generation in the back-end

Let us take the same app from above, but this time the PDF document will be generated in a PHP-based service.

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv='X-UA-Compatible' content='IE=edge' />
    <meta http-equiv='Content-Type' content='text/html;charset=UTF-8'/>
     
    <script id='sap-ui-bootstrap' type='text/javascript' src='https://openui5.hana.ondemand.com/resources/sap-ui-core.js' data-sap-ui-theme='sap_bluecrystal' data-sap-ui-libs='sap.m,sap.ui.commons'></script>
     
    <script>      
        var oModel = new sap.ui.model.json.JSONModel({ name: "Name", age: 30 });
        var p = new sap.m.Page( {
          title: "Generate PDF",
          content: [
            new sap.m.Label({ text: "Name:" }),
            new sap.m.Input({ value: "{/name}" } ),
            new sap.m.Label({ text: "Age:" }),
            new sap.m.Input({ value: "{/age}" } ),
            new sap.m.Button({ text: "Generate PDF", press: function(evt) {
              var n = evt.getSource().getModel().getProperty("/name");
              var a = evt.getSource().getModel().getProperty("/age");
               
              window.open("http://some.where/?name=" + n + "&age=" + a, "_blank");
            }})
          ]
        } );
       
      var app = new sap.m.App({ pages: [ p ] }).placeAt("content");
      app.setModel(oModel);
    </script>
     
    </head>
    <body class='sapUiBody'>
      <div id='content'></div>
    </body>
</html>

Pushing the button “Generate PDF” this time opens a new window/tab with the specified location passing the form data as HTTP GET parameters. Usually, you will pass bigger amounts of data to the output processing and might consider using HTTP POST. So, what does the back-end script look like:

<?php
  require('fpdf.php');
  $name = $_GET['name'];
  $age = $_GET['age'];
  $pdf = new FPDF();
  $pdf->AddPage();
  $pdf->SetFont('Arial', 'B', 12);
  $pdf->Cell(40, 10, 'This is ' . $name . ' aged ' . $age);
  $pdf->Output();
?>

The PHP script simply fetches the two parameters (data), creates a new object of type FPDF and uses a few – easy to understand – methods to put some content into the document. Again, fpdf comes with a variety of examples and tutorials to show you how to use it. It takes some time to get used to the positioning of elements etc. But once you have got acquainted to fpdf, it’s quite easy to create large document with different types of content.

In this post, I have shown two different approaches on where to create PDF in (mobile) apps that are based on UI5. Both example were kept as simple as possible ignoring some best practices for UI5. Of course, there are different libraries for PDF output and the same approaches apply for word documents etc. If you know better tools for the job – other than jsPDF and fpdf – feel free to leave a comment. Also, if you’re trying to implement PDF as part of (mobile) apps and require help, please do not hesitate to get in touch.