Transforming rdl files into pdf with the power of JavaScript

I need assistance converting my rdl report to PDF using Javascript. It would greatly help if I could accomplish this task with just the OpenReport() function to avoid having to convert it into a ppt later on. I am currently working in CRM online.

Below is the code snippet I am using:

 function OpenReport() {
                debugger;
                var formType = Xrm.Page.ui.getFormType();
                if(formType != 1){
                Xrm.Page.ui.setFormNotification("Please wait while system is generating pdf...", "INFO", "pdfGen");
                var rdlName = "KalorikBrandPresentationv4.rdl"; //Replace with your report name
                var entityType = "10060"; //Replace
                var entityGuid = Xrm.Page.data.entity.getId();
                var recordId = entityGuid.replace("{","").replace("}","");
                var reportGuid = "ea721b27-44a6-ea11-9688-005056ba540f"; //Replace with your report guid
                var url = Xrm.Page.context.getClientUrl() + "/crmreports/viewer/viewer.aspx?action=run&context=records&helpID=" + rdlName + "&id=%7b" + reportGuid + "%7d&records=%7b" + recordId + "%7d&recordstype=" + entityType;


            var responseSession = getReportingSession(reportGuid,rdlName,recordId);
            convertResponseToPDF(responseSession,rdlName);
        }


function convertResponseToPDF(responseSession,reportName) {
        debugger;
        var pth = encodeURI(Xrm.Page.context.getClientUrl() + "/Reserved.ReportViewerWebControl.axd? 
        ReportSession=" + responseSession[0]+"&Culture=1033&CultureOverrides=True&UICulture=1033&UICultureOverrides=True&ReportStack=1&ControlID=" + responseSession[1] +"&OpType=Export&FileName=Public&ContentDisposition=OnlyHtmlInline&Format=PDF");
        var base64PDFString;
        var retrieveEntityReq = new XMLHttpRequest();
        retrieveEntityReq.open("GET", pth, true);
        retrieveEntityReq.setRequestHeader("Accept", "*/*");
        retrieveEntityReq.responseType = "arraybuffer";
        retrieveEntityReq.onreadystatechange = function () {
            if (retrieveEntityReq.readyState == 4 && retrieveEntityReq.status == 200) {
                var binary = "";
                var bytes = new Uint8Array(this.response);
    
                for (var i = 0; i < bytes.byteLength; i++) {
                    binary += String.fromCharCode(bytes[i]);
                }
                base64PDFString = btoa(binary);
                console.log(base64PDFString);
                createNotesAttachment(base64PDFString,reportName);
            }
        };
        
       
        retrieveEntityReq.send();
    }

Answer №1

Have you followed the instructions here

I recall working on downloading reports as PDF in 2016 online. This should be useful.

You may need to make some changes to the code.

function runReportToPrint() {

    var invoicenumber = Xrm.Page.getAttribute("invoicenumber").getValue()
        if (invoicenumber != null) {
            invoicenumber = invoicenumber.substring(4, 9);
            var params = getReportingSession();
            var newPth = Xrm.Page.context.getClientUrl() + "/Reserved.ReportViewerWebControl.axd?ReportSession=" + params[0] + "&Culture=1033&CultureOverrides=True&UICulture=1033&UICultureOverrides=True&ReportStack=1&ControlID=" + params[1] + "&OpType=Export&FileName=" + invoicenumber + "&ContentDisposition=OnlyHtmlInline&Format=PDF";
            window.open(newPth, "_self");
            encodePdf(params);
        } else {
            alert("Invoice ID is Missing");
        }
}

function getReportingSession() {
    var recordId = Xrm.Page.data.entity.getId();
    recordId = recordId.replace('{', '').replace('}', '');

    var strParameterXML = "<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'><entity name='invoice'><all-attributes /><filter type='and'><condition attribute='invoiceid' operator='eq' value='" + recordId + "' /> </filter></entity></fetch>";
    var pth = Xrm.Page.context.getClientUrl() + "/CRMReports/rsviewer/QuirksReportViewer.aspx";
    var retrieveEntityReq = new XMLHttpRequest();

    retrieveEntityReq.open("POST", pth, false);
    retrieveEntityReq.setRequestHeader("Accept", "*/*");
    retrieveEntityReq.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    retrieveEntityReq.send("id=%7B" + reportGuid + "%7D&uniquename=" + Xrm.Page.context.getOrgUniqueName() + "&iscustomreport=true&reportnameonsrs=&reportName=" + reportName + "&isScheduledReport=false&p:CRM_invoice=" + strParameterXML);

    var x = retrieveEntityReq.responseText.lastIndexOf("ReportSession=");
    var y = retrieveEntityReq.responseText.lastIndexOf("ControlID=");

    var ret = new Array();
    ret[0] = retrieveEntityReq.responseText.substr(x + 14, 24);
    ret[1] = retrieveEntityReq.responseText.substr(x + 10, 32);

    return ret;
}

function encodePdf(responseSession) {

    var retrieveEntityReq = new XMLHttpRequest();
    var pth = Xrm.Page.context.getClientUrl() + "/Reserved.ReportViewerWebControl.axd?ReportSession=" + responseSession[0] + "&Culture=1033&CultureOverrides=True&UICulture=1033&UICultureOverrides=True&ReportStack=1&ControlID=" + responseSession[1] + "&OpType=Export&FileName=Public&ContentDisposition=OnlyHtmlInline&Format=PDF";
    retrieveEntityReq.open("GET", pth, true);
    retrieveEntityReq.setRequestHeader("Accept", "*/*");
    retrieveEntityReq.responseType = "arraybuffer";
    retrieveEntityReq.onreadystatechange = function () {

        if (retrieveEntityReq.readyState == 4 && retrieveEntityReq.status == 200) {
            var binary = "";
            var bytes = new Uint8Array(this.response);

            for (var i = 0; i < bytes.byteLength; i++) {
                binary += String.fromCharCode(bytes[i]);
            }
            var bdy = btoa(binary);
            createNote(bdy);
        }
    };

    retrieveEntityReq.send();
}

function createNote(data) {

    var note = {};

    var recordId = Xrm.Page.data.entity.getId();
    recordId = recordId.replace('{', '').replace('}', '');

    var invoicenumber = Xrm.Page.getAttribute("invoicenumber").getValue()
        invoicenumber = invoicenumber.substring(4, 9);

    var refInvoice = new Object();
    refInvoice.LogicalName = "invoice";
    refInvoice.Id = recordId;

    note.ObjectId = refInvoice;
    note.ObjectTypeCode = refInvoice.LogicalName;

    note.Subject = "Invoice: " + invoicenumber;
    note.MimeType = "application/pdf";
    note.DocumentBody = data;
    note.FileName = invoicenumber + ".pdf";

    XrmServiceToolkit.Rest.Create(
        note,
        "AnnotationSet",
        function (result) {
        //Alert user
        alert("Note Created");
        //Refresh data so user sees newly created note
        Xrm.Page.data.refresh(false);

    },
        function (error) {
        alert(error.message);
    },
        true);
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

There seems to be a hiccup in the system as we are unable

Upon visiting the URL address http://localhost:3000/test, I intend to load a log message. However, an error is returned stating "Cannot GET /test". Below is the code snippet in question: import express from 'express'; import React from 'rea ...

Odd gap beside Bootstrap5 navbar that needs fixing

While working on a layout featuring a left-sided nav-bar menu, I encountered an odd blank space between the navbar and the main content area. Can anyone shed light on why this space appears and how to eliminate it? For reference, here is the code snippet: ...

Create a CSS menu that centers the links

Here is the CSS code I am using for my horizontal menu: nav { height: 40px; width: 100%; background: #F00; font-size: 11pt; font-family: Arial; font-weight: bold; position: relative; border-bottom: 2px solid # ...

What is the best way to send an axios request in a Vue component to a route created by an Adonis controller?

My WidgetController.js file is responsible for handling CRUD operations on the database. Within this controller, there is a method/generator called * create (request, response) which returns widget attributes in a response and also inserts a new row into t ...

How can you use ES6 pure Javascript to set the src attribute of an html collection of images from an array of paths as values for each image?

Currently, I have an array filled with different src values like [path1, path2, path3], and a corresponding HTML collection which has the same number of elements as the array. I am looking for a way to assign each value from the array to set the src attrib ...

Modify the size of images while shuffling using Javascript

Hey there! I've got some bootstrap thumbnails set up and I'm using a script to shuffle the images inside the thumbnails or a element within the li. It's working fine, but some of the images are coming out larger or smaller than others. I&apo ...

Apply a custom filter to ng-repeat results

Asking for advice on how to iterate over an array using ng-repeat and filter the contained objects based on a function property. Find more details in this Plunker link. Let's say we have an object like this: vm.show1 = function(){ return true; }; ...

Currently, I am encountering a problem as I attempt to iterate through a dynamic table

I have a table containing various elements. An example row is Jack Smith with multiple rows like this: col1 col2 col3 col4 col5 col6 col7 col8 jack smith 23 Y Y error error_code error_desc The table is ...

(JS) utilizing an external .js function by using the <script> tag

Looking to execute the function cookiefix() from main.js, which is linked at the bottom of my HTML file. echo '<body>'; if(!isset($_COOKIE['clicked'])) { if(!isset($_COOKIE['count'])) { echo '<script type="text/ ...

Is it possible to retrieve specific elements from another html file using AJAX?

Looking to use vanilla JS for loading content dynamically without needing a page refresh. The goal is to retrieve content from another HTML file when a menu option is selected, while targeting either the body or a specific class. Is it possible to achieve ...

Ways to modify Angular pipe without specifying data types

I am in the process of extracting an Angular pipe from an application to a library. The current pipe is tied to specific types, but I want to change it to use generic types while maintaining type safety. Original Pipe: import { Pipe, PipeTransform } fr ...

Guide to binding input type= 'email' in Knockout.js

My project utilizes KnockoutJS with MVC. I am seeking assistance on determining whether an emailId is valid or invalid. Based on this validation, I need to dynamically enable/disable a button and set an error title for the corresponding textbox. Below is ...

Tips on initiating a $http.get request every second using a service

I am working on an angular application that includes a $http.get request. While it currently functions properly, I need it to be executed every second in order to retrieve new data. Service: angular.module('adf.widget.liveCharts') .service(&a ...

What is the reason for the failure of the require("perf_hooks") function?

My understanding is that "perf_hooks" is a component of Node.js. However, when I run tests with npm test, it fails for me and shows the following error (some file names have been altered): Error: ENOENT: no such file or directory, open 'perf_hooks&apo ...

Unable to modify the hover color on the image or icon

After creating a circle icon with an image in the center, I wanted to make the image change colors on hover. The main focus of the icon is the circle itself. In my attempt to achieve this effect, I included the following code for the circle icon: .circle- ...

The nested jade elements are failing to render

If I have a jade setup with 3 files as follows: 1. //layout.jade doctype html html body block content 2. //index.jade extends layout block content h1 Animals block cat block dog 3. //animals.jade extends index block cat p Meow block ...

Is it beneficial to create a separate component for React form elements?

I've come across advice that suggests when unsure, turning an element into a component is a good idea. But what are the actual benefits of converting form elements like <input /> into components? Let's consider the following example: cons ...

Using API call responses to initiate a render in React

As a newcomer to React, I'm facing an issue with passing the results of my API call to another component file in order to trigger a render. Can anyone provide a straightforward explanation of what steps I need to take? In my code, I make a call to th ...

Tips for resolving the issue of the '$interval is not a function' error in AngularJS

When I click on the up/down arrows, I am attempting to continuously increase/decrease a value using AngularJS $interval function. However, I keep encountering an error message that says "TypeError: $interval is not a function." Can someone please help me s ...

Inserting a variable into a JSON string

Within my code, I have a basic variable containing strings that are converted into a JSON object. My goal is to create an input field where a person's name can be entered and added to the text. The current setup looks like this var text = '{"st ...