The CreatorCon Call for Content is officially open! Get started here.

Export PDF button Not working sometimes.

practicalin
Tera Contributor

Hello Everyone,

 

I have been facing an issue with a button "Export PDF".

I have a ui action calling out the script include to perform this action.

The same script include is being used by different ui actions as well.

The buttons is working sometimes, sometimes not clickable.

Sometimes its clickable and sometimes its not generating data.

 

Not sure whats wrong,

Will be pasting my script here.

Script Include:

var CustomExportPDF = Class.create();
CustomExportPDF.prototype = Object.extendsObject(AbstractAjaxProcessor, {

    getFieldsFromFormView2: function(_table, _view, _format) {

        var table = this.getParameter("sysparm_table_form") || _table;
        var view = this.getParameter("sysparm_view_form") || _view;
        var format = this.getParameter("sysparm_format_form") || _format;

        var r = (format == 'json') ? {} : [];
        var form_view = new GlideRecord("sys_ui_view");
        if (form_view.get("name", view)) {
            var section = new GlideRecord("sys_ui_section");
            section.addQuery("view", form_view.getUniqueValue());
            section.addQuery("name", table);
            section.query();
            while (section.next()) {
                var field = new GlideRecord("sys_ui_element");
                field.addQuery("sys_ui_section", section.getUniqueValue());
                field.orderBy("position");
                field.query();
                while (field.next()) {
                    switch (format) {
                        case "json":
                            r[field.element.getValue()] = {};
                            break;
                        default:
                            r.push(field.element.getValue());
                            break;
                    }
                }
            }
        }

        switch (format) {
            case "string":
                return r.toString();
            default:
                return r;
        }
    },

    getFieldsFromFormView: function(_table, _view, _format) {

        var table = this.getParameter("sysparm_table_form") || _table;
        var view = this.getParameter("sysparm_view_form") || _view;
        var format = this.getParameter("sysparm_format_form") || _format;

        // gs.info(table + " " + view)

        var r = (format == 'json') ? {} : [];
        var form_view = new GlideRecord("sys_ui_view");
        if (form_view.get("name", view)) {
            var form_container = new GlideRecord("sys_ui_form");
            form_container.addQuery("view", form_view.getUniqueValue());
            form_container.addQuery("name", table);
            form_container.addNullQuery("sys_user");
            form_container.setLimit(1);
            form_container.query();
            gs.log("sys_ui_form query: " + form_container.getEncodedQuery(), "Export PDF - ITSM");
            while (form_container.next()) {
                var form_container_section = new GlideRecord("sys_ui_form_section");
                form_container_section.addQuery("sys_ui_form", form_container.getUniqueValue());
                form_container_section.orderBy("position");
                form_container_section.query();
                while (form_container_section.next()) {
                    var section = new GlideRecord("sys_ui_section");
                    if (section.get(form_container_section.sys_ui_section + '')) {
                        var field = new GlideRecord("sys_ui_element");
                        field.addQuery("sys_ui_section", section.getUniqueValue());
                        field.orderBy("position");
                        field.query();
                        while (field.next()) {
                            switch (format) {
                                case "json":
                                    r[field.element.getValue()] = {};
                                    break;
                                default:
                                    r.push(field.element.getValue());
                                    break;
                            }
                        }
                        switch (format) {
                            case "json":
                            default:
                                r.push(".end_section");
                                break;
                        }
                    }
                }
            }
        }
        // gs.log("fields: " + r, "Export PDF - ITSM")
        switch (format) {
            case "string":
                return r.toString();
            default:
                return r;
        }
    },

    getRelatedListsFromFormView: function(_table, _view) {

        var table = this.getParameter("sysparm_table_form") || _table;
        var view = this.getParameter("sysparm_view_form") || _view;
        var r = [];

        var form_view = new GlideRecord("sys_ui_view");
        if (form_view.get("name", view)) {
            var related_list = new GlideRecord("sys_ui_related_list");
            related_list.addQuery("view", form_view.getUniqueValue());
            related_list.addQuery("name", table);
            related_list.query();
            if (related_list.next()) {
                var related_list_entry = new GlideRecord("sys_ui_related_list_entry");
                related_list_entry.addQuery("list_id", related_list.getUniqueValue())
                related_list_entry.addQuery("related_list", "DOES NOT CONTAIN", "REL:");
                related_list_entry.orderBy("position");
                related_list_entry.query();
                while (related_list_entry.next()) {
                    r.push(related_list_entry.related_list.getValue());
                }

            }
        }

        return r;
    },

    getFieldsFromListView: function(table, view, parentTable, user) {
        var r = [];
        var form_view = new GlideRecord("sys_ui_view");
        if (form_view.get("name", view)) {

            var user_view = this.getviewForUser(table, view, parentTable, user, form_view.getUniqueValue());

            if (!user_view.hasNext()) {
                user_view = this.getviewForUser(table, view, parentTable, "", form_view.getUniqueValue());
                if (!user_view.hasNext()) {
                    user_view = this.getviewForUser(table, view, "", user, form_view.getUniqueValue());
                    if (!user_view.hasNext()) {
                        user_view = this.getviewForUser(table, view, "", "", form_view.getUniqueValue());
                        user_view.next();
                    } else {
                        user_view.next();
                    }
                } else {
                    user_view.next();
                }
            } else {
                user_view.next();
            }
            //return user_view.getUniqueValue()
            var list_element = new GlideRecord("sys_ui_list_element");
            list_element.addQuery("list_id", user_view.getUniqueValue());
            list_element.orderBy("position");
            list_element.query();
            while (list_element.next()) {
                r.push(list_element.element.getValue())
            }
        }
        return r;
    },

    getviewForUser: function(table, view, parentTable, user, viewId) {
        var sys_ui_list = new GlideRecord("sys_ui_list");
        sys_ui_list.addQuery("name", table);

        if (parentTable)
            sys_ui_list.addQuery("parent", parentTable);
        else
            sys_ui_list.addNullQuery("parent");
        if (user)
            sys_ui_list.addQuery("sys_user", user);
        else
            sys_ui_list.addNullQuery("sys_user");

        sys_ui_list.addQuery("view", viewId);
        sys_ui_list.setLimit(1);
        sys_ui_list.query();
        return sys_ui_list;
    },

    fontFamilyArial: function() {
        return gs.getProperty("hc.itms.font_family.arial.sys_id");
    },

    pdfTemplateUIPage: function() {
        return gs.getProperty("hc.itms.ui_page.pdf_template.sys_id");
    },

    isValidSysId: function(sysId) {
        // Check if the sys_id is exactly 32 characters long
        if (sysId.length !== 32) {
            return false;
        }

        // Check if the sys_id contains only hexadecimal characters (0-9, a-f, A-F)
        var regex = /^[0-9a-fA-F]{32}$/;
        return regex.test(sysId);
    },

    generatePDF: function(_table, _view, _sysId) {
        var table = this.getParameter("sysparm_table_form") || _table;
        var view = _view || this.getParameter("sysparm_view_form") || "";
        var sysId = this.getParameter("sysparm_format_sysId") || _sysId;
        var format = "string";

        gs.log("Table " + table + "  " + "View " + view + ' ' + 'sysID ' + sysId, 'pdfSource');

        var target = new GlideRecord(table);
        target.get(sysId);

        var fields = this.getFieldsFromFormView(table, view, format);
        fields = fields.split(",");
        gs.log("fields " + fields, 'pdfSource');

        var row = "";
        var globalBody = "";

        var displays1 = [];
        var displays2 = [];
        var displaysglobal = [];

        var isInSplit = false;
        var colspanValue = 1;
        var auxDisplays = [];

        var fieldsCount = fields.length;

        var not_allowed_fields = ["com_glideapp_servicecatalog_veditor", "activity.xml", "sc_req_item_delivery_plan.xml", "cxs_table_search.xml", "attached_knowledge"];
        // gs.info("FIELDS : " + fields)

        for (var i = 0; i < fieldsCount; i++) {
            gs.log("fieldscount  " + fieldsCount, 'pdfSource');


            if (fields[i] == ".begin_split") {
                gs.log("insideif  ", 'pdfSource');
                if (i > 0) {
                    displays1 = auxDisplays
                    globalBody += this.generateHTMLSection(target, displays1, [], isInSplit)
                    gs.log("1 - globalBody : " + globalBody, "Export PDF - ITSM")

                    displays1 = [];
                    displays2 = [];
                    auxDisplays = [];
                }


                isInSplit = true;
                continue
            }

            if (fields[i] == ".split") {

                gs.print(
                    "[ES SPLIT1]\n" +
                    displays1.toString() + "\n" +
                    auxDisplays.toString() + "\n" +
                    "[ES SPLIT1]"
                );

                isInSplit = true;
                displays1 = auxDisplays
                auxDisplays = [];

                gs.print(
                    "\n[ES SPLIT2]\n" +
                    "1-->" + displays1.toString() + "\n" +
                    "2-->" + auxDisplays.toString() + "\n" +
                    "3-->fieldsCount:" + fieldsCount + " -->" + i + "\n" +
                    "[ES SPLIT2]"
                );

                continue;
            }

            if (fields[i] == ".end_split") {
                displays2 = auxDisplays
                globalBody += this.generateHTMLSection(target, displays1, displays2, isInSplit);
                // gs.log("2 - globalBody : " + globalBody, "Export PDF - ITSM")

                displays1 = [];
                displays2 = [];
                auxDisplays = [];

                isInSplit = false;

                continue;
            }

            if (fields[i] == ".end_section") {
                if (isInSplit)
                    displays2 = auxDisplays;
                else
                    displays1 = auxDisplays;


                globalBody += this.generateHTMLSection(target, displays1, displays2, isInSplit);
                // gs.log("3 - globalBody : " + globalBody, "Export PDF - ITSM")

                displays1 = [];
                displays2 = [];
                auxDisplays = [];
                isInSplit = false;
                continue
            }


            if (this.isValidSysId(fields[i]))
                continue;

            if (not_allowed_fields.indexOf(fields[i]) == -1)
                auxDisplays.push(fields[i]);

            if ((fieldsCount - 1) == i) {
                if (isInSplit)
                    displays2 = auxDisplays;
                else
                    displays1 = auxDisplays;
                globalBody += this.generateHTMLSection(target, displays1, displays2, isInSplit)
            }

        }

        var pdfGenerator = new sn_pdfgeneratorutils.PDFGenerationAPI;
        var pageProperties = {
            "PageSize": "LETTER",
            "PageOrientation": 'PORTRAIT',
            "TopOrBottomMargin": "36",
            "LeftOrRightMargin": "24",
            "GeneratePageNumber": "false",
            "fontFamilySysId": this.fontFamilyArial(),
        };

        var modifiedHTML = "";
        var ui_page_template = new GlideRecord("sys_ui_page");
        ui_page_template.get(this.pdfTemplateUIPage());
        modifiedHTML = ui_page_template.html.getValue().toString();
        var tableLabel = target.getClassDisplayValue();
        var tableName = target.getTableName();
        var stats = {
            "title": tableLabel + " Details",
            "datetime": new GlideDateTime() + " " + gs.getSession().getTimeZoneName(),
            "runby": gs.getUserDisplayName(),
            "tablename": tableName
        };

        var attachmentsHTML = this.getAttachmentsHTML(target);
        var related_listHTML = "";

        var related_lists = this.getRelatedListsFromFormView(target.getTableName(), view, target.getUniqueValue());
        var related_lists_info = this.getRelatedListInfo(target, related_lists, view);

        for (var related_list in related_lists_info) {
            var current_rl = related_lists_info[related_list];
            var current_fields = current_rl.fields;

            if (current_rl.data.length == 0)
                continue

            var headers = "";
            var rows = "";
            for (var i = 0; i < current_rl.labels.length; i++) {
                headers += (
                    "<th class='form-title'  >" + (i == 0 ? "&#8593;" : "") + current_rl.labels[i] + "</th>"
                );
            }
            for (var i = 0; i < current_rl.data.length; i++) {
                var row = "";
                for (var j = 0; j < current_fields.length; j++) {
                    row += (
                        "<td>" + current_rl.data[i][current_fields[j]] + "</td>"
                    );
                }
                rows += "<tr " + ((i % 2) == 1 ? "style='background-color:#eee;'" : "") + " >" + row + "</tr>";
            }
            related_listHTML += (
                "<table class='stats'>" +
                "<tbody>" +
                "<tr>" +
                "<td class='font-weight-bold' colspan='1'> Table: </td>" +
                "<td> " + related_lists_info[related_list].table + "(" + related_list + ") </td>" +
                "</tr>" +
                "<tr>" +
                "<td class='font-weight-bold' colspan='1'> Query condition: </td>" +
                "<td> " + related_lists_info[related_list].query + " </td>" +
                "</tr>" +
                "<tr>" +
                "<td class='font-weight-bold' colspan='1'> Sort order: </td>" +
                "<td> " + related_lists_info[related_list].order + " </td>" +
                "</tr>" +
                "</tbody>" +
                "</table>" +

                "<table class='table'>" +
                "<thead>" +
                "<tr>" + headers + "</tr>" +
                "</thead>" +
                "<tbody>" +
                rows +
                "</tbody>" +
                "</table><br/>"
            );
        }


        modifiedHTML = modifiedHTML.
        replaceAll("$body_string$", globalBody).
        replaceAll("$form_title$", tableLabel + " - " + target.getDisplayValue()).
        replaceAll("$attachments$", attachmentsHTML).
        replaceAll("$related_list$", related_listHTML).
        replaceAll("$email_chain_html$", this.getEmailsHTML(sysId));
        for (var key in stats) {
            modifiedHTML = modifiedHTML.replaceAll("$stats." + key + "$", stats[key]);
        }

        // gs.log( "modifiedHTML: " + modifiedHTML, "Export PDF - ITSM");
        var newModifiedHTML = this.replaceIixImageSources(modifiedHTML);

        // gs.log( "newModifiedHTML: " + newModifiedHTML, "Export PDF - ITSM");

        var result = pdfGenerator.convertToPDF(newModifiedHTML, table, sysId, tableLabel + " - " + target.getDisplayValue(), this.fontFamilyArial());
        return JSON.stringify(result);
        //return modifiedHTML;
    },
    deletePDF: function(_attachment_id) {
        var attachment_id = this.getParameter("sysparm_attachment_id") || _attachment_id;
        var att = new GlideRecord("sys_attachment");
        if (att.get(attachment_id))
            att.deleteRecord();

    },
    getRelatedListInfo: function(target, related_lists, view) {
        var r = {};
        for (var i = 0; i < related_lists.length; i++) {



            var rlist_info = related_lists[i].split(".");
            var table = rlist_info[0];
            var fieldForQuery = rlist_info[1];
            var queryDisplay = "";
            var sortDisplay = "";
            var query = fieldForQuery + "=" + target.getUniqueValue();
            var fields = this.getFieldsFromListView(table, view, target.getTableName(), gs.getUserID());
            if (view && fields.length == 0)
                fields = this.getFieldsFromListView(table, "", target.getTableName(), gs.getUserID());

            gs.print("[RELATED LIST]: " + table + " - " + fields + " -> " + view)

            var fieldsDisplay = [];
            var data = [];
            var rl = new GlideRecord(table);
            rl.addEncodedQuery(query);
            rl.orderBy(fields[0]);
            rl.query();
            var recour_counter = 0;
            while (rl.next()) {
                if (!queryDisplay)
                    queryDisplay = rl.getElement(fieldForQuery).getLabel() + "=" + target.getDisplayValue();
                if (!sortDisplay)
                    sortDisplay = rl.getElement(fields[0]).getLabel() + " in ascending order";

                var obj = {};
                for (var j = 0; j < fields.length; j++) {
                    obj[fields[j]] = rl.getElement(fields[j]).getDisplayValue();
                    if (recour_counter == 0)
                        fieldsDisplay.push(rl.getElement(fields[j]).getLabel())
                }
                recour_counter++;
                data.push(obj)
            }
            r[table] = {
                "table": rl.getClassDisplayValue(),
                "query": queryDisplay,
                "order": sortDisplay,
                "data": data,
                "fields": fields,
                "labels": fieldsDisplay,
            }
        }
        return r;
    },
    generateHTMLSection: function(target, col1, col2, separated) {
        var arrayUtil = new global.ArrayUtil();
        var checkfields;

        var joiner = gs.getProperty("hc.itsm.joiner.fields");
        joiner = joiner.split(",");

        var leaver = gs.getProperty("hc.itsm.leaver.fields");
        leaver = leaver.split(",");

        var orderguide = gs.getProperty("hc.itsm.order_guide.fields");
        orderguide = orderguide.split(",");

        var mover = gs.getProperty("hc.itsm.mover.fields");
        mover = mover.split(",");

        var category = target.getElement("u_employee_movement_category");
        if (category == "leaver") {
            col1 = arrayUtil.diff(col1, joiner);
            col1 = arrayUtil.diff(col1, mover);
        } else if (category == "joiner") {
            col1 = arrayUtil.diff(col1, leaver);
            col1 = arrayUtil.diff(col1, mover);
        } else if (!category) {
            col1 = arrayUtil.diff(col1, joiner);
            col1 = arrayUtil.diff(col1, leaver);
            col1 = arrayUtil.diff(col1, mover);
            col1 = arrayUtil.diff(col1, orderguide);
        }
        var maxLength;
        if (col1.length > col2.length)
            maxLength = col1.length;
        else
            maxLength = col2.length;
        var colspanValue = separated ? "1" : "3";
        var row = "";

        for (var i = 0; i < maxLength; i++) {
            row += "<tr>";
            if (col1[i]) {
                if (!target.getElement(col1[i])) {
                    gs.print("A >>> " + col1[i])
                }

                row += (
                    "<td class='form-label' colspan='1' > " + target.getElement(col1[i]).getLabel() + " </td>" +
                    "<td class='form-value' colspan='" + colspanValue + "' > <div style='max-width:675px;'> " + target.getElement(col1[i]).getDisplayValue() + "</div> </td>"
                );
            } else {
                row += (
                    "<td colspan='1'></td> <td colspan='1'></td>"
                );
            }

            if (separated && col2[i]) {
                row += (
                    "<td class='form-label' colspan='1' > " + target.getElement(col2[i]).getLabel() + " </td>" +
                    "<td class='form-value' colspan='" + colspanValue + "' > <div> " + target.getElement(col2[i]).getDisplayValue() + "</div> </td>"
                );
            }
            row += "</tr>";
        }
        return row;
    },

    getAttachmentsHTML: function(target) {
        var r = "";
        var attachmentAPI = new GlideSysAttachment();
        var attachment = attachmentAPI.getAttachments(target.getTableName(), target.getUniqueValue());
        while (attachment.next()) {
            if (attachment.content_type.getValue().indexOf("image") > -1) {
                r += (
                    "<div> <img src='" + this.getAttachmentBase64(attachment) + "' /> <br> <span>" + attachment.file_name.getValue() + "</span></div>"
                );
            } else {
                r += (
                    "<div style='width:100%;'><span>" + attachment.file_name.getValue() + "</span></div>"
                );
            }



        }
        return r;
    },

    getAttachmentBase64: function(attachmentGR) {
        var base64ImageStr = GlideStringUtil.base64Encode(
            new GlideSysAttachment().getBytes(attachmentGR)
        );
        return "data&colon;image/png;base64," + base64ImageStr + "";
    },

    getEmailsHTML: function(targetID) {
        var emails = new GlideRecord("sys_email");
        emails.addEncodedQuery("instance=" + targetID + "^headersLIKEX-ServiceNow-Source:EmailClient^type=sent^NQinstance=" + targetID + "^type=received^ORDERBYsys_created_on");
        emails.query();
        var response = "";
        while (emails.next()) {
            response += (
                "<div class='email_container_iterator' >" +
                "<b>Subject: </b>" + emails.subject + "<br>" +
                "<b>To: </b>" + emails.direct + "<br>" +
                "<b>CC: </b>" + emails.copied + "<br>" +
                "<b>Attachments: </b>" + this.getAttachmentsName(emails.getUniqueValue()) + "<br>" +
                emails.body + "\n" +
                "</div>"
            );
        }
        return response;
    },

    getAttachmentsName: function(emailID) {
        var r = [];
        var sys_email_attachment = new global.TicketCaseEmailUtils().getList(
            "sys_email_attachment",
            "email=" + emailID + "^content_disposition=attachment"
        );
        while (sys_email_attachment.next()) {
            r.push(sys_email_attachment.file_name + '');
        }
        return r.toString()
    },

    /**
     * Processes a raw HTML string, finds <img> tags with src="/[sys_id].iix",
     * and replaces them with src="/sys_attachment.do?sys_id=[sys_id]".
     *
     * @Param {string} htmlString - The HTML content to process.
     * @returns {string} - The updated HTML with fixed <img> src values.
     */
    replaceIixImageSources: function(htmlString) {
        // Define the regex pattern to match "/[sys_id].iix"
        var regex = /src="\/([a-f0-9]{32})\.iix"/gi;

        return htmlString.replace(regex, (match, sysId) => {
            return `src="/sys_attachment.do?sys_id=${sysId}"`;
        });
    },

    type: 'CustomExportPDF'
});
8 REPLIES 8

@practicalin 

1 ticket is not exporting data to PDF.

Does that user have read access to that ticket?

which data is not getting generated ? entire variable information?

If my response helped please mark it correct and close the thread so that it benefits future readers.

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

@Ankur Bawiskar 
all records are same, i have a feeling it is form load issue or browser issue. Cause when i impersonate i am able to export on those records, but he is nto able to do in Edge browser. And he is not willing to move to diff browser. 

I have a feeling it is just browser or cache issue.

@practicalin 

when you impersonate that person and load the form did you check any browser console error when form loads?

any browser console error when button is clicked?

share the sample PDF which is generated for actual record where data is coming.

If my response helped please mark it correct and close the thread so that it benefits future readers.

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

Ankur Bawiskar
Tera Patron
Tera Patron

@practicalin 

why so much customization?

what's your exact business requirement?

Sometimes you can achieve your requirement with OOTB feature.

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader