PDF Reports in Oracle APEX using jsPDF – Simple, Matrix & Master-Detail Source Code Included

Oracle Application Express is a rapid development tool for Web applications on the Oracle database.
Post Reply
admin
Posts: 2117
Joined: Fri Mar 31, 2006 12:59 am
Location: Pakistan
Contact:

PDF Reports in Oracle APEX using jsPDF – Simple, Matrix & Master-Detail Source Code Included

Post by admin »

You will learn how to generate different report formats step by step, including:

Simple PDF report
Matrix (tabular) report
Master–Detail PDF report

The video focuses on structuring data properly and rendering it into well-formatted PDF documents using jsPDF, making it useful for ERP, reporting, and web application scenarios.

This tutorial is ideal for developers who want to implement client-side PDF generation and build professional reports directly from JavaScript.

JavaScript File URLs

https://cdnjs.cloudflare.com/ajax/libs/ ... umd.min.js
https://cdnjs.cloudflare.com/ajax/libs/ ... ble.min.js

If you want to download then you can right click above links and then save as to download and upload in Oracle APEX static files in APP or Workspace level and then using those links. You can further check the version if you are comfortable to make any update might required.

Function and Global Variable Declaration

Code: Select all

apex.jQuery(function () {

  /* =====================================================
     Shared logo loader (HTML image from Workspace Files)
     ===================================================== */

  const logoUrl = '#WORKSPACE_FILES#erpstuff_logo_small.png';
  const logoImg = new Image();
  logoImg.src = logoUrl;

  // Utility function: wait for image to load before generating PDF
  function waitForLogoAndRun(callback) {
    if (!logoImg.complete) {
      logoImg.onload = callback;
    } else {
      callback();
    }
  }

  /* =====================================================
     DEPARTMENT-WISE EMPLOYEE PDF
     ===================================================== */
  window.generatePDF = function () {
    waitForLogoAndRun(() => {

      const { jsPDF } = window.jspdf;
      const doc = new jsPDF('p', 'pt', 'a4');

      const rawData = JSON.parse($v("P34_JSON"));

      const pageWidth = doc.internal.pageSize.getWidth();
      const pageHeight = doc.internal.pageSize.getHeight();

      const drawHeader = () => {
        doc.addImage(logoImg, 'PNG', 20, 10, 60, 40);
        doc.setFontSize(18);
        doc.setFont(undefined, 'bold');
        doc.text('Employee Report', pageWidth / 2, 40, { align: 'center' });
      };

      const drawFooter = () => {
        const pageNum = doc.getCurrentPageInfo().pageNumber;
        const pageCount = doc.getNumberOfPages();
        doc.setFontSize(10);
        doc.text(`Page ${pageNum} of ${pageCount}`, pageWidth - 80, pageHeight - 20);
      };

      rawData.forEach((dept, index) => {
        if (index > 0) doc.addPage();

        drawHeader();

        doc.autoTable({
          startY: 60,
          head: [['Emp No', 'Name', 'Job', 'Salary', 'Comm']],
          body: dept.employees.map(e => [
            e.empno,
            e.ename,
            e.job,
            e.sal,
            e.comm || 0
          ]),
          theme: 'grid',
          styles: { fontSize: 10 },
          didDrawPage: () => {
            drawHeader();
            drawFooter();
          }
        });
      });

      window.open(doc.output('bloburl'));
    });
  };

  /* =====================================================
     JOB × LOCATION MATRIX PDF
     ===================================================== */
  window.generateMatrixPDF = function () {
    waitForLogoAndRun(() => {

      const { jsPDF } = window.jspdf;
      const doc = new jsPDF('l', 'pt', 'a4');

      const rawData = JSON.parse($v("P34_JSON2"));
      const pageWidth = doc.internal.pageSize.getWidth();

      const jobs = [...new Set(rawData.map(r => r.job))];
      const locs = [...new Set(rawData.map(r => r.loc))];

      const head = [['JOB', ...locs]];
      const body = jobs.map(job => {
        const row = [job];
        locs.forEach(loc => {
          const rec = rawData.find(r => r.job === job && r.loc === loc);
          row.push(rec ? rec.cnt : 0);
        });
        return row;
      });

      const drawHeader = () => {
        doc.addImage(logoImg, 'PNG', 20, 10, 60, 40);
        doc.setFontSize(18);
        doc.setFont(undefined, 'bold');
        doc.text('Employee Count Matrix', pageWidth / 2, 40, { align: 'center' });
      };

      drawHeader();

      doc.autoTable({
        startY: 70,
        head: head,
        body: body,
        theme: 'grid',
        styles: { fontSize: 10, halign: 'center' },
        columnStyles: { 0: { halign: 'left' } }
      });

      window.open(doc.output('bloburl'));
    });
  };

  /* =====================================================
     MASTER-DETAIL PDF
     ===================================================== */
  window.generateMasterDetailPDF = function () {
    waitForLogoAndRun(() => {

      const { jsPDF } = window.jspdf;
      const doc = new jsPDF('p', 'pt', 'a4');
      const data = JSON.parse($v("P34_JSON_MD"));

      const pageWidth = doc.internal.pageSize.getWidth();
      const pageHeight = doc.internal.pageSize.getHeight();

      const drawHeader = () => {
        doc.addImage(logoImg, 'PNG', 20, 10, 60, 40);
        doc.setFontSize(18);
        doc.setFont(undefined, 'bold');
        doc.text('Master-Detail Employee Report', pageWidth / 2, 40, { align: 'center' });
      };

      const drawFooter = () => {
        const pageNum = doc.getCurrentPageInfo().pageNumber;
        const pageCount = doc.getNumberOfPages();
        doc.setFontSize(10);
        doc.text(`Page ${pageNum} of ${pageCount}`, pageWidth - 80, pageHeight - 20);
      };

      data.forEach((dept, idx) => {
        if (idx > 0) doc.addPage();

        drawHeader();

        // Master info
        doc.setFontSize(14);
        doc.setFont(undefined, 'bold');
        doc.text(`Department: ${dept.dname} (${dept.deptno})`, 40, 70);

        // Detail table
        doc.autoTable({
          startY: 80,
          head: [['Emp No', 'Name', 'Job', 'Salary']],
          body: dept.employees.map(e => [e.empno, e.ename, e.job, e.sal]),
          theme: 'grid',
          styles: { fontSize: 10 },
          didDrawPage: () => {
            drawHeader();
            drawFooter();
          }
        });
      });

      window.open(doc.output('bloburl'));
    });
  };

});
Explanation
https://youtu.be/q8YNqKuZ6sc
Malik Sikandar Hayat
Oracle ACE Pro
info@erpstuff.com
Post Reply

Who is online

Users browsing this forum: No registered users and 3 guests