- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
06-17-2025 12:38 PM
Hi,
We are currently working on a proof of concept (POC) in our Personal Developer Instance (PDI) within ServiceNow. As part of this POC, we are generating a PDF file from an HTML Template and attaching it to the Risk Response Task table.
However, instead of a PDF, our requirement is to generate and attach a Word (DOCX) document. We would like to know if there is a native or recommended way in ServiceNow to convert a PDF file to a Word (DOCX) file.
To explore alternatives, we attempted two different approaches:
Custom Azure-hosted Solution: We developed our own solution to convert PDFs to DOCX, hosted on Azure. While the integration with ServiceNow was successful, the resulting file was corrupted. Upon checking Azure logs, it appears that the file being received is already corrupted at the time of transmission.
Open Source API (ConvertAPI): We also integrated ConvertAPI to achieve the conversion. Unfortunately, the result was the same — a corrupted Word document was returned.
Given these challenges, we are seeking guidance or a working solution to successfully convert and attach a Word (DOCX) file in the Risk Response Task record in ServiceNow.
We would greatly appreciate any support or recommendations you could provide.
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
06-20-2025 09:14 AM - edited 06-20-2025 09:15 AM
Hello @srujancherr , These are simple things you can do this on your own by modifying it,
For images, i am not 100% sure.
If your original query is answered then Mark helpul and Accept it as solution
Regards
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-10-2025 07:30 AM
Hi @srujancherr
You can check all attached variables in script and then set their values like this.
Just attach any incident values in template and use this script, it will dynamically change those variables into values.
getContentForWordTemp: function(temp, rec) {
var tempGr = new GlideRecord('sn_doc_html_template');
tempGr.addQuery('sys_id', temp);
tempGr.query();
while (tempGr.next()) {
var text = tempGr.getValue('html_script_body');
var recGr = new GlideRecord('incident');
if (!recGr.get(rec)) {
return;
}
var matches = text.match(/\$\{([^}]+)\}/g);
if (matches) {
for (var i = 0; i < matches.length; i++) {
var placeholder = matches[i];
var field = placeholder.replace('${', '').replace('}', '');
var value = recGr.getDisplayValue(field) || '';
var regex = new RegExp('\\$\\{' + field + '\\}', 'g');
text = text.replace(regex, value);
}
}
var HtmlHead = "<html xmlns:o='urn:schemas-microsoft-com:office:office' " +
"xmlns:w='urn:schemas-microsoft-com:office:word' " +
"xmlns='http://www.w3.org/TR/REC-html40'>" +
"<head><meta charset='utf-8'></head><body>";
var content = HtmlHead;
content += "<h1><strong>" + tempGr.getDisplayValue('name') + "</strong></h1><br>";
content += "<div>" + text + "</div>";
content += "</body></html>";
var fileName = tempGr.getDisplayValue('name') + '.doc';
var contentType = 'application/msword';
var attachment = new GlideSysAttachment();
var attachmentID = attachment.write(recGr, fileName, contentType, content);
}
},
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
06-19-2025 11:00 AM
Hi @srujancherr , try this approach
Script include:
getContentForWordTemp: function(temp, rec) {
var list = [];
var tempGr = new GlideRecord('sn_doc_html_template');
tempGr.addQuery('sys_id', temp);
tempGr.query();
while (tempGr.next()) {
var text = tempGr.getValue('html_script_body');
var object = {};
var fileName = tempGr.getDisplayValue('name') + '.doc';
var contentType = 'application/msword';
var HtmlHead = "<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:w='urn:schemas-microsoft-com:office:word' xmlns='http://www.w3.org/TR/REC-html40' ><head><meta charset='utf-8'></head><body>";
var content = HtmlHead + '<h1>' + tempGr.getDisplayValue('name') + '</h1>' + '<p style="margin-top:-20px;"> <strong style="font-size: 30px"> <div style="margin-top:-30px;">' + text + '</div>';
var recGr = new GlideRecord('incident');
recGr.get(rec);
var attachment = new GlideSysAttachment();
var attachmentID = attachment.write(recGr, fileName, contentType, content);
}
},
UI Action on incident for test:
var recordId = current.sys_id.toString();
var documentTemplateId = '6e8a52ac83de2e507993c6b6feaad361';
new sn_doc.tempDoc().getContentForWordTemp(documentTemplateId, recordId);
action.setRedirectURL(current);
You can try and change code and table as per your requirement
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
06-20-2025 05:17 AM
Hello @srujancherr , did you try this?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
06-20-2025 08:11 AM
Hi @Muhammad Salar ,
This is the main issue, I'm getting when I use two different tables with two different scopes
[0:00:00.320] Script completed in scope global: script
Script execution history and recovery available here
Time: 0:00:00.197 id: dev192667_1[glide.10] primary_hash=-97966150 (connpid=41923) for: SELECT sys_restricted_caller_access0.`description`, sys_restricted_caller_access0.`target_scope`, sys_restricted_caller_access0.`source`, sys_metadata0.`sys_updated_on`, sys_metadata0.`sys_class_name`, sys_restricted_caller_access0.`rca_type`, sys_metadata0.`sys_id`, sys_metadata0.`sys_updated_by`, sys_metadata0.`sys_created_on`, sys_restricted_caller_access0.`target_table`, sys_metadata0.`sys_name`, sys_metadata0.`sys_scope`, sys_metadata0.`sys_created_by`, sys_restricted_caller_access0.`target_type`, sys_metadata0.`sys_mod_count`, sys_restricted_caller_access0.`source_type`, sys_restricted_caller_access0.`target`, sys_metadata0.`sys_package`, sys_metadata0.`sys_update_name`, sys_restricted_caller_access0.`source_scope`, sys_restricted_caller_access0.`operation`, sys_restricted_caller_access0.`source_table`, sys_restricted_caller_access0.`status`, sys_metadata0.`sys_policy` FROM (sys_restricted_caller_access sys_restricted_caller_access0 INNER JOIN sys_metadata sys_metadata0 ON sys_restricted_caller_access0.`sys_id` = sys_metadata0.`sys_id` ) WHERE sys_restricted_caller_access0.`source_scope` = 'global' AND sys_metadata0.`sys_scope` = sys_restricted_caller_access0.`target_scope` /* dev192667002, gs:DFDD6EBC83DEAA90FBA8C4E0DEAAD319, tx:c4800b7c8312ea90fba8c4e0deaad30c, hash:-97966150 */
For RCA records with global targets, target type cannot be scope. Only source-to-target records are supported when the target is global
Source descriptor is empty while recording access for table sn_doc_html_template: no thrown error
Security restricted: Read operation on table 'sn_doc_html_template' from scope 'Global' was denied because the source could not be found. Please contact the application admin.
Security restricted: Read operation on table 'sn_doc_html_template' from scope 'Global' was denied. The application 'Global' must declare a cross scope access privilege. Please contact the application admin to update their access requests.
*** Script: Template not found with sys_id: b473cc60838aaa10fba8c4e0deaad323
I'm running the code in Background scripts to test, as we know background scripts run Global scope.
Tried creating Cross Scope, Source as Global and Target Scope as Document template, but getting error saying we cannot create Global as Source Scope.
let me know how should i solve this type of issues.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
06-20-2025 08:23 AM
Hello @srujancherr , I have tried this and it is working for me, validate these
Create script include and add this function which i posted earlier
Create ui action on table, e.g incident then call that function from UI Action code which i posted
Change template sysid in ui action to your templated sys id
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
06-20-2025 09:09 AM
Hi @Muhammad Salar ,
Its working fine, Thankyou
But, there were few gaps missing, like in HTML template I mapped few fields, but when I generate they are not getting printed with Incident table field values, and Images in the template were not showing, except these two things everything is good.