Skip to main content

This content has been archived and is no longer being updated.

Links may not function; however, this content may be relevant to outdated versions of the product.

Exporting a chart in a scheduled report to a PDF file

Suggest edit Updated on September 1, 2015

When a scheduled report with a chart is exported to a PDF file, the chart is not automatically included in the PDF file. However, you can use the pyEmbedChartUsingPhantomJS HTML rule and the pyCallPhantomJS activity rule to implement a solution that can export the chart in a scheduled report to a PDF file.

This behavior is different from when you export reports from the Report Viewer. When you export a report with a chart from the Report Viewer, the chart is included in the PDF file. Including charts when you export a report is an effective way to visually communicate report details.

This solution uses PhantomJS. You can download PhantomJS from the following website: http://phantomjs.org/

Prerequisites

Before you begin:

  • Comment out the code in the pyEmbedChartUsingPhantomJS HTML rule.
  • Comment out all steps in the pyCallPhantomJS activity rule.

Process

1. Create a JavaScript file (for example, chartURL.js), and copy the following code into that file. Include a user ID and password in this file.

[*]Code for the JavaScript file[*]

[*]

// Passing hard coded user id and password and passing URL and chartName dynamically
var page = require('webpage').create();
page.viewportSize = {
    width: 2000,
    height: 3000
};
page.settings.userName = ""; //username to be used to run the report
page.settings.password = ""; //password to be used to run the report
page.settings.clearMemoryCaches = true;
/*getting variables passed from activity*/
var reportURL = phantom.args[0];
var chartName = phantom.args[1];
var phantomLocation = phantom.args[2];
var chartPath=phantomLocation+chartName+".png";
phantom.clearCookies();
try{
page.open(reportURL, function() {
    var waitNRun = function() {
        console.log("In wait");
        result = page.evaluate(function() {
            var divs = document.getElementsByTagName('div');
            var chartDiv;
            for (var i = 0; i < divs.length; i++) {
                if (divs[i].getAttribute('id') != null && divs[i].getAttribute('id').indexOf('ichartDiv') == 0) {
                    var reg = /^\d+$/;
                    if (reg.test(divs[i].getAttribute('id').split('ichartDiv')[1])) {
                        chartDiv = divs[i];
                        break;
                    }
                } else if (divs[i].getAttribute('id') != null && divs[i].getAttribute('id').indexOf('staticChart') == 0) {
                    var reg = /^\d+$/;
                    if (reg.test(divs[i].getAttribute('id').split('staticChart')[1])) {
                        chartDiv = divs[i];
                        break;
                    }
                }
            }
            var curtop = 0,
                curleft = 0;
            var chartDivForTop = chartDiv;
            if (chartDivForTop.offsetParent) {
                do {
                    curtop += chartDivForTop.offsetTop;
                    curleft += chartDivForTop.offsetLeft;
                } while (chartDivForTop = chartDivForTop.offsetParent);
            }
            return [chartDiv.offsetHeight, chartDiv.offsetWidth, curtop, curleft];
        });
        try {
            console.log('Crop brand new to : ' + result[0] + "x" + result[1] + "x" + result[2] + "x" + result[3]);
            page.clipRect = {
                top: result[2] + 10,
                left: result[3],
                width: result[1],
                height: result[0] - 45
            };
            window.setTimeout(function() {
                             
                page.render(chartPath);
                phantom.exit();
            }, 20000);
        } catch (err) {
            console.log('exception');
            phantom.exit(1);
        }
    }
    setTimeout(waitNRun, 5000);
});
}catch(err){
console.log("error occured in js file");
}

[*]

 

2. Use the pyEmbedChartUsingPhantomJS HTML rule to call the activity to obtain the image byte stream and append the image byte stream to the PDF stream.

[*]pyEmbedChartUsingPhantomJS HTML rule[*]

[*]

<%  
 HashStringMap keys = new HashStringMap();
        keys.putString("pxObjClass", "Rule-Obj-Activity");
        keys.putString("pyClassName", "Rule-Obj-Report-Definition");
        keys.putString("pyActivityName", "pyCallPhantomJS");
    ParameterPage paramsPage = new ParameterPage();  
    paramsPage.putString("InsHandle", tools.getPrimaryPage().getString(".pyReportDefinition.pzInsKey"));
    ClipboardPage chartPage=tools.getPrimaryPage().getPage(".pyReportDefinition.pyUI.pyChart");
String ChartName=chartPage.getString(".pyGraphType")+chartPage.getString(".pySubType")+com.pegarules.generated.pega_rules_datetime.getCurrentTimeStampUnique().replace(".","").replace("GMT","");
       ChartName = ChartName.trim();
    paramsPage.putString("ChartName",ChartName);
tools.doActivity(keys , null, paramsPage);

String encodedImage = tools.getPrimaryPage().getString("encodedImage");
String imgTag = "<img src='data:image/png;base64,"+ encodedImage +"' />";
imgTag = imgTag.trim();
%>
 <%
  =imgTag
  %>

[*]

 

3. Use the pyCallPhantomJS activity rule to invoke the PhantomJS WebKit, which calls the JavaScript file that you created (chartURL.js).

[*]a. Obtain the report URL dynamically and set the URL to a variable.[*]

[*]

ClipboardPage cp=tools.findPage("pxRequestor"); /*Get the requestor page*/
if(cp!=null){
    String reqContextURI= cp.getProperty(".pxReqContextURI").getStringValue()+"/PRServlet";
   String reqPathInfoReal= cp.getProperty(".pxReqPathInfoReal").getStringValue();
  String insHandle=tools.getParamValue("InsHandle");
  insHandle=insHandle.replaceAll(" ","%20").replaceAll("#","%23");
reportURL=reqContextURI+reqPathInfoReal+"?pyActivity=%40baseclass.WBRun&InsHandle="+insHandle;
}else{
  oLog.infoForced("requestor page is null");
}

[*]

 

[*]b. Set the PhantomJS location and the JavaScript file location as local variables by using the Property-Set method of an activity.[*]

[*]

Local.phantomPath=”"\\\\ shared_location \\phantom\\phantomjs"
Local.phantomLocation=”"\\\\ shared_location \\phantom\\"
Local. chartURL="\\\\ shared_location \\phantom\\chartURL.js"

[*]

 

[*]c. Call PhantomJS by using the Java step of an activity.[*]

[*]

try{
  
  java.lang.Process process = java.lang.Runtime.getRuntime().exec(phantomPath+" "+chartURL+" "+reportURL+" "+tools.getParamValue("ChartName")+" "+phantomLocation);
process.waitFor(); 
    
}
catch(Exception e)
{
oLog.error("Exception occurred while calling phantom JS ",e);    
}

[*]

 

[*]d. Obtain the chart bytecode and add it to the primary page.[*]

[*]

try{
  String chartPath = phantomLocation+tools.getParamValue("ChartName")+".png"; 
  oLog.infoForced("chartPath=="+chartPath);
  java.awt.image.BufferedImage image = javax.imageio.ImageIO.read(new java.io.File(chartPath));
  java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream(); 
  javax.imageio.ImageIO.write(image, "png", baos); 
  byte[] res=baos.toByteArray();
  String encodedImage = com.sun.org.apache.xerces.internal.impl.dv.util.Base64.encode(baos.toByteArray());
  oLog.infoForced("encodedImage=="+encodedImage);
 tools.findPage("TmpExportResultsPage").putString("encodedImage",encodedImage);
} catch(Exception e) { 
  oLog.infoForced("In exception=="+e.getMessage());
}

[*]

 

Did you find this content helpful? YesNo

0% found this useful

Have a question? Get answers now.

Visit the Support Center to ask questions, engage in discussions, share ideas, and help others.

We'd prefer it if you saw us at our best.

Pega.com is not optimized for Internet Explorer. For the optimal experience, please use:

Close Deprecation Notice
Contact us