on 02-18-2021 02:03 AM
ServiceNow recently released a new plugin for the platform (Paris onwards) to enable better support for custom PDF generation using script. Unfortunately the only documentation on this new feature set you will find is in KB0866613, which does not go very far in explaining how to use the API. I'm sure ServiceNow will eventually document this, or even build some full featured platform functionality around it, but for now I hope this article will get you started.
The new API appears to be based on iText7, which is a major improvement over the old GeneralPDF that was based on iText5. The newer version of iText is much better at handling HTML conversion, and once you start to explore the feature set, there is quite a lot you can do with just plain HTML and CSS.
API Overview
At the time of writing this article, there are two known methods available on the API.
Parameter | Type | Description |
html | String | The HTML content to convert to a PDF |
targetTable | String | The table name to attach the generated PDF to |
targetSysId | String | sys_id of the record to attach the generated PDF to |
filename | String | The file to to save the generated PDF as |
pageProperties | Object | Javascript object with properties used during PDF generation |
fontSysId | String | sys_id of a font family record on the 'sys_pdf_generation_font_family' table |
property | Type | Description |
HeaderImageAttachmentId | String | sys_id of an attachment record |
HeaderImageAlignment | String | One of: 'LEFT', 'CENTER', 'RIGHT' |
PageSize | String | One of: 'LEGAL', 'LETTER', 'A4' |
GeneratePageNumber | String | One of: 'true', 'false' |
TopOrBottomMargin | String | Number as a string e.g. '72' |
LeftOrRightMargin | String | Number as a string e.g. '36' |
Example
var pageProperties = {
HeaderImageAttachmentId: 'attachment_sys_id',
HeaderImageAlignment: 'LEFT',
PageSize: 'A4',
GeneratePageNumber: 'true',
TopOrBottomMargin: '72',
LeftOrRightMargin: '36'
};
var html = '<h1>Hello World</h1>';
new sn_pdfgeneratorutils.PDFGenerationAPI().convertToPDFWithHeaderFooter(html, 'incident', 'incident_sys_id', 'My First PDF', pageProperties, 'font_family_sys_id');
Parameter | Type | Description |
html | String | The HTML content to convert to a PDF |
targetTable | String | The table name to attach the generated PDF to |
targetSysId | String | sys_id of the record to attach the generated PDF to |
filename | String | The file to to save the generated PDF as |
fontSysId | String | sys_id of a font family record on the 'sys_pdf_generation_font_family' table |
Example
var html = '<h1>Hello World</h1>';
new sn_pdfgeneratorutils.PDFGenerationAPI().convertToPDF(html, 'incident', 'incident_sys_id', 'My First PDF', 'font_family_sys_id');
On the face of it, it would appear as though the convertToPDFWithHeaderFooter is the more flexible of the two methods, however as you'll see below, we can actually control the entire document ourselves with HTML and CSS and just use the convertToPDF method.
The CSS 3 specification sets out functionality for paged media, for example printing. When it comes to PDF we can use the paged media rules to define how the document should be generated using the ServiceNow PDFGenerationAPI / iText7.
The @page rule allows us to specify details about the pages we will be generating, including the margins, size, orientation, page numbering rules etc.
Example
<style>
@page {
size: A4 landscape;
margin-left: 1cm;
margin-top: 3cm;
margin-right: 1cm;
margin-bottom: 3cm;
@bottom-right {
font-family: sans-serif;
font-weight: bold;
font-size: 1em;
content: counter(page);
}
}
</style>
<h1>
Hello World!
</h1>
Resulting PDF
The creation of headers and footers is equally as easy. This uses a feature called 'Running elements'. At first they may not make much sense in how you define them, but see the below for an example.
<style>
@page {
size: A4 landscape;
margin-left: 1cm;
margin-top: 3cm;
margin-right: 1cm;
margin-bottom: 3cm;
@top-center {
font-family: sans-serif;
font-weight: bold;
font-size: 1em;
content: element(runningPageHeader);
}
}
#pageHeader {
position: running(runningPageHeader)
}
</style>
<div id="pageHeader">
My Header!
</div>
<h1>
Hello World!
</h1>
Resulting PDF
How this works
The div element with the id 'pageHeader' would normally be rendered in the position its included in the code on the page, however the style block of the code contains a CSS rule for the element #pageHeader, specifying position: running(runningPageHeader). This removes the element from the rendered page and adds it into a css variable, in our case the variable is called 'runningPageHeader'. Once the content is in the variable, we can use that same variable name to include it as content in the @top-center rule using content: element(runningPageHeader).
This can be a difficult concept to get your head around at first, and it can get more complicated when you want to include a page number in your custom HTML header content too. For example:
<style>
@page {
size: A4 landscape;
margin-left: 1cm;
margin-top: 3cm;
margin-right: 1cm;
margin-bottom: 3cm;
@top-center {
font-family: sans-serif;
font-weight: bold;
font-size: 1em;
content: element(runningPageHeader);
}
}
#pageHeader {
position: running(runningPageHeader)
}
#currentPageNumber:before {
content: counter(page)
}
</style>
<div id="pageHeader">
My Header! <span id="currentPageNumber"/>
</div>
<h1>
Hello World!
</h1>
Resulting PDF
Images are also possible with relative ease. You can use the usual img elements in your html, and even use absolute URLs to image content, be aware though that if the image is hosted on your ServiceNow instance, you need to make sure the image is publicly accessible. Attachments against records won't work unfortunately as the PDF generation API is not authenticated to your instance.
Example
<style>
@page {
size: A4 landscape;
margin-left: 1cm;
margin-top: 3cm;
margin-right: 1cm;
margin-bottom: 3cm;
@top-center {
font-family: sans-serif;
font-weight: bold;
font-size: 1em;
content: element(runningPageHeader);
}
}
#pageHeader {
position: running(runningPageHeader)
}
#currentPageNumber:before {
content: counter(page)
}
</style>
<div id="pageHeader">
My Header! <span id="currentPageNumber"/>
</div>
<h1>
Hello World!
</h1>
<img src="URL_TO_IMAGE" width="100px"/>
Resulting PDF
It is possible to add and use custom fonts into the PDFs that you generate. I've only tried this with TTF (TrueType) fonts, though it may work with other formats too. It's possible to add more than one font to a PDF, see the following example.
When using the API, the last parameter of both methods is the font family sys_id, you can only supply one sys_id to the method, which is why you add multiple fonts to the same Font Family record.
To use the font in your document, you simply specify the font-family CSS attribute in your CSS
Example
<style>
@page {
size: A4 landscape;
margin-left: 1cm;
margin-top: 3cm;
margin-right: 1cm;
margin-bottom: 3cm;
@top-center {
font-family: sans-serif;
font-weight: bold;
font-size: 1em;
content: element(runningPageHeader);
}
}
#pageHeader {
position: running(runningPageHeader)
}
#currentPageNumber:before {
content: counter(page)
}
.angry-birds-font {
font-family: AngryBirds;
}
.flow-font {
font-family: Flow;
}
</style>
<div id="pageHeader">
My Header! <span id="currentPageNumber"/>
</div>
<h1 class="flow-font">
Hello World!
</h1>
<h1 class="angry-birds-font">
Angry Birds
</h1>
Resulting PDF
Hopefully this article has helped you get to grips with the new PDFGenerationAPI. I have only scratched the surface of the CSS paged media rules, but a little Googling around should get you loads of information on how to use it.
Why not have a play with this on your developer instance and post some screenshots here to show everyone else what you've been able to achieve, I'd love to see some of what you've managed to create.
As always, if this content has helped you, please remember to mark it as helpful so that it can reach as many people as possible.
Callum
Thanks for a great article! This is really helpful!
Good to know we can now get current page number by calling counter(page).
Is there by any chance a way to get total number of pages? To build something like "page 2 of 5".
Yep absolutely, have a look at the documentation here https://www.w3.org/TR/css-page-3/#page-based-counters
TL;DR
counter(pages)
Thanks! Got it!
What is the concept behind 'sys_pdf_generation_font_family' table? Do we need to attach fonts to the record?
Great stuff! Thanks a lot for taking the time to explore this functionality and document your findings.
Just a small remark: The code example for convertToPDF is using a wrong method name (convertToPDFWithHeaderFooter). I thought you might want to correct it.
Good spot, thank you!
Updated 🙂
I have updated the article to include an example with custom fonts.
Great timing. I just started looking into how to append data to a preexisting PDF so this looks like it might be useful. Hopefully I can find a way to read in a current PDF and add to it. If not, i might have to go back to trying to get GeneralPDF to work.
If you're wanting to fill in an existing PDF I guess you'll have to stick with what you've got. There may be more methods on the new API, but you'd have to guess at their names and how to use them as the properties/methods of the API Object are not enumerable via the usual for(prop in obj) method.
Thanks for the input. I'm relatively new to using Service Now so i'm curious as to why we couldn't reach out to them to get details on what methods are available for the API.
First off, thank you for this article, it was driving me crazy a few months ago that I couldn't find anything for this...
I've taken up the job of converting my existing PDF creations from iText5 to iText7, hoping that table-lines and other styling will get better now.
So taking your first example:
1) HeaderImageAttachmentId, I've got company logo images I want to add to the header, but these are obviously added to the db_image library, but this expects an attachment id? An attachment to what? to the targetTable+targetSysId? That doesn't make any sense...
2) f̶o̶n̶t̶_̶f̶a̶m̶i̶l̶y̶_̶s̶y̶s̶_̶i̶d̶,̶ ̶I̶'̶v̶e̶ ̶l̶o̶o̶k̶e̶d̶ ̶a̶t̶ ̶t̶h̶e̶ ̶s̶y̶s̶_̶p̶d̶f̶_̶g̶e̶n̶e̶r̶a̶t̶i̶o̶n̶_̶f̶o̶n̶t̶_̶f̶a̶m̶i̶l̶y̶ ̶t̶a̶b̶l̶e̶ ̶a̶n̶d̶ ̶t̶r̶i̶e̶d̶ ̶a̶d̶d̶i̶n̶g̶ ̶a̶ ̶l̶i̶n̶e̶ ̶w̶i̶t̶h̶ ̶'̶A̶r̶i̶a̶l̶'̶ ̶i̶n̶ ̶i̶t̶ ̶a̶n̶d̶ ̶u̶s̶i̶n̶g̶ ̶t̶h̶a̶t̶ ̶s̶y̶s̶_̶i̶d̶ ̶f̶o̶r̶ ̶t̶h̶e̶ ̶c̶o̶n̶v̶e̶r̶t̶T̶o̶P̶D̶F̶W̶i̶t̶h̶H̶e̶a̶d̶e̶r̶F̶o̶o̶t̶e̶r̶-̶f̶u̶n̶c̶t̶i̶o̶n̶,̶ ̶b̶u̶t̶ ̶t̶h̶a̶t̶ ̶d̶o̶e̶s̶n̶'̶t̶ ̶s̶e̶e̶m̶ ̶t̶o̶ ̶w̶o̶r̶k̶,̶ ̶s̶o̶ ̶h̶o̶w̶ ̶s̶h̶o̶u̶l̶d̶ ̶t̶h̶e̶ ̶r̶e̶c̶o̶r̶d̶ ̶b̶e̶ ̶f̶i̶l̶l̶e̶d̶?̶ <edit>Missed this in your post... weird... as it's such a good explanation!</edit>
Ok... after re-reading my post: I'm not attacking you or anything, I'm just lost at what to use here 🙂
Hopefully we can make this Article complete with everyone's questions and answers!
Ps, did get a fix script to create a <hello world> PDF using this new function, so there is hope!
var pageProperties = {
HeaderImageAttachmentId: '',
HeaderImageAlignment: 'LEFT',
PageSize: 'A4',
GeneratePageNumber: 'true',
TopOrBottomMargin: '72',
LeftOrRightMargin: '36'
};
var html = '<style> @page { size: A4 portrait; margin-left: 1cm; margin-top: 3cm; margin-right: 1cm; margin-bottom: 3cm;' +
'@bottom-right { font-family: Arial; font-weight: bold; font-size: 1em; content: counter(page); }' +
'@top-center { font-family: Arial; font-size: 10pt; font-weight: bold; font-size: 1em; content: element(runningPageHeader); }' +
'}' +
'#pageHeader { position: running(runningPageHeader) }' +
' .left-align { text-align: left; }' +
' .right-align { text-align: right; }' +
' .lined-table { border-collapse: collapse; border: 1px solid black; }' +
' .lined-td { padding-left: 10px; border-collapse: collapse; border: 1px solid black; }' +
' .font1 { font-family: Arial; }' +
' .font2 { font-family: Flow; }' +
' .font3 { font-family: Verdana; }' +
' .font4 { font-family: AngryBirds; }' +
'</style>' +
'<div id="pageHeader">' +
'<table width="100%" cellspacing="0" cellpadding="0">' +
'<tbody><tr>' +
'<td width="50%" class="left-align"><img src="image-150.png" /></td>' +
'<td width="50%" class="right-align"><img src="image2.jpg" /></td>' +
'</tr><tr><td>Testing Font</td></tr></tbody></table>' +
'</div>' +
'<table width="100%" class="lined-table">' +
'<tbody><tr style="border-bottom:2px solid black;">' +
'<td width="30%" class="lined-td font1"><b>First and last name</b><br /><b>participant</b></td>' +
'<td width="15%" class="lined-td font2"><b>Reg. nr.</b><br /><b>participant</b></td>' +
'<td width="15%" class="lined-td font3"><b>Birthdate</b><br /><b>participant</b></td>' +
'<td width="10%" class="lined-td font4"><b>Comp.</b><br /> </td>' +
'<td width="30%" class="lined-td" style="font-family: arial;"><b>Signature participant</b><br/>USING A BLUE PEN</td>' +
'</tr></tbody></table>' +
'<table width="100%" class="lined-table"><tbody>';
for (var i = 0; i < 7; i++) {
html +=
'<tr>' +
'<td width="30%" class="lined-td"> </td>' +
'<td width="15%" class="lined-td"> </td>' +
'<td width="15%" class="lined-td"> </td>' +
'<td width="10%" class="lined-td"> </td>' +
'<td width="30%" class="lined-td"> </td></tr>';
}
html += '</tbody></table>';
var target_table = 'target_table';
var target_id = 'target_id';
//sys_pdf_generation_font_family table is empty so last variable is empty
new sn_pdfgeneratorutils.PDFGenerationAPI().convertToPDFWithHeaderFooter(html, target_table, target_id, 'iText7 PDF 11', pageProperties, '');
So I was testing with this in a fix script and I'm thrilled to finally have proper control over table-lines again!
Though for some reason, no font-family seems to work... Everything is Times New Roman (and I loathe that font...)
It would seem that over time with more testing things even out:
var pageProperties = {
HeaderImageAttachmentId: '',
HeaderImageAlignment: 'LEFT',
PageSize: 'A4',
GeneratePageNumber: 'false',
TopOrBottomMargin: '72',
LeftOrRightMargin: '36'
};
var css_text = '<style> @page { size: A4 portrait; margin-left: 1cm; margin-top: 3cm; margin-right: 1cm; margin-bottom: 3cm;' +
'@top-center { font-family: Arial; font-size: 10pt; font-weight: bold; font-size: 1em; content: element(pageHeader); }' +
'@bottom-left { font-family: Arial; font-size: 10pt; font-weight: bold; font-size: 1em; content: element(pageFooter); }' +
'@bottom-right{ content: counter(page) " / " counter(pages); font-size:8pt; }' +
'}' +
' .pageHeader { position: running(pageHeader) }' +
' .pageFooter { position: running(pageFooter) }' +
' .left-align { text-align: left; }' +
' .right-align { text-align: right; }' +
' .lined-table { border-collapse: collapse; border: 1px solid black; }' +
' .lined-td { padding-left: 10px; border-collapse: collapse; border: 1px solid black; }' +
' .font1 { font-family: Arial; }' +
' .font2 { font-family: arial; }' +
' .font3 { font-family: Verdana; }' +
' .font4 { font-family: Tahoma; }' +
' .content { font-family: Verdana; }' +
'</style>';
var header_text = '<div class="pageHeader">' +
'<table width="100%" cellspacing="0" cellpadding="0">' +
'<tbody><tr>' +
'<td width="50%" class="left-align"><img src="Print-logo-workorder.jpg" width="200px" /></td>' +
//'<td width="50%"><img src="EngieLogo.jpg" align="left" /></td>' +
'<td width="50%" class="right-align"><img src="Example.jpg" width="200px" /></td>' +
'</tr></tbody></table>' +
'</div>';
var footer_text = '<div class="pageFooter">' +
'<table width="100%" style="font-size: 10pt; font-family: tahoma; position: relative;" cellspacing="0" cellpadding="0"><tbody><tr>' +
'<td style="font-family: tahoma;"><span style="font-size: 11pt; font-weight: bold;">Companyname<br />Department</span><br /><span style="font-size: 9pt; line-height: 12pt;">Addressline<br /> Telephonenumber</span><br /><span style="font-size: 9pt; font-weight: bold;">email@email.com - www.email.com</span><br /><span style="font-size: 7pt;">Legal line</span></td>' +
'</tr></tbody></table>' +
'</div>';
var body_text = '<div class="content">' +
'<table width="100%" class="lined-table font1">' +
'<tbody><tr style="border-bottom:2px solid black;">' +
'<td width="30%" class="lined-td"><b>First and last name</b><br /><b>participant</b></td>' +
'<td width="15%" class="lined-td"><b>Reg. nr.</b><br /><b>participant</b></td>' +
'<td width="15%" class="lined-td"><b>Birthdate</b><br /><b>participant</b></td>' +
'<td width="10%" class="lined-td"><b>Comp.</b><br /> </td>' +
'<td width="30%" class="lined-td" style="font-family: arial;"><b>Signature participant</b><br/>USING A BLUE PEN</td>' +
'<table width="100%" class="lined-table"><tbody>';
for (var i = 0; i < 120; i++) {
body_text +=
'<tr>' +
'<td width="30%" class="lined-td"> </td>' +
'<td width="15%" class="lined-td"> </td>' +
'<td width="15%" class="lined-td"> </td>' +
'<td width="10%" class="lined-td"> </td>' +
'<td width="30%" class="lined-td"> </td></tr>';
}
body_text += '</tbody></table></div>';
var html = css_text+header_text+footer_text+body_text;
//gs.info(html);
var target_table = 'target_table';
var target_id = 'target_sys_id';
//dd06dbcc1b7ae8103cd411b1b24bcb56 is sys_id for sys_pdf_generation_font_family
new sn_pdfgeneratorutils.PDFGenerationAPI().convertToPDFWithHeaderFooter(html, target_table, target_id, 'iText7 PDF EN', pageProperties, 'dd06dbcc1b7ae8103cd411b1b24bcb56');
Resulting in:
So I'm quite satisfied with the headers, footers and CSS 🙂
Also since these images can be put into the header like this, it doesn't matter anymore that I don't know what HeaderImageAttachmentId should be!
Hi Chris,
Good work 🙂
The only thing to mention is that there is no need to use the convertToPDFWithHeaderFooter method as you are defining the page size and margins yourself using the @page rule in the CSS. Instead just use the convertToPDF method which I documented in the original article.
Callum
Hi Callum,
Ah that is good to know, I tested it and works perfectly, so I'll be using that from now on!
I thought that the option with HeaderFooter would ensure those to things, but the CSS does this instead, perfect!
Chris
Hey, thanks a lot for this article, really helpful but i have a question:
Is it possible to create pages within the html string like
var html =" Page1 Content"+
"Some text on Page 1"+
//New Content should start on page 2
"Page2 Content"+
"Some text on Page 2";
In the old GeneralFormAPI there is something like that
var pages = [
{heading: '<h1>My First PDF</h1><p>First page content</p>' },
{heading: '<p color="red">Second page content</p>' },
{heading: '<table border="1"><tr bgcolor="pink"><td>Pink rocks!</td><td align="center">Center</td></tr><tr><td colspan="2" align="center">Second row</td></tr></table>' },
{heading: '<img src="' + getAttachmentBase64(att) + '"/>'}
];
gs.debug('Create the PDF!');
// createPDF(html, pages)
// if you don't want to use pages just supply the html argument
formAPI.createPDF('', pages);
Hey Andrew,
That actually is possible, using PageBreak in your CSS:
.pageBreak { page-break-after : always; }
.pageBreakBefore { page-break-before : always; }
Then I added this to the body where I want the newpage:
<div class="pageBreak">
I use the pageBreakBefore in my header as well, so I can print multiple invitations to 1 pdf.
Thank you very much.
So simple and it works fine 😃
Hi, great content!
The only thing I can't get to work is images in my header html. I'm using an image I've uploaded to system UI > Images and have made sure it's publicy accessible using an incognito browser.
I call my code that lives in a script include:
var styleHTML = '<style>'+
'@page {' +
'size: A4 portrait;' +
'margin-left: 1cm;' +
'margin-top: 1cm;' +
'margin-right: 1cm;' +
'margin-bottom: 1cm;' +
'@bottom-right { content: counter(page) " / " counter(pages); font-size:8pt; }' +
'}' +
'@page :first { ' +
'size: A4 portrait;' +
'margin-left: 1cm;' +
'margin-top: 2cm;' +
'margin-right: 1cm;' +
'margin-bottom: 1cm;' +
'@top-left {font-family: sans-serif; font-weight: bold; font-size: 1em; content: element(runningPageHeader);}' +
'}' +
' #pageHeader { position: running(pageHeader) }' +
' </style>';
var headerHTML = '<div id="pageHeader">'+
'<img src="Logo.png" width="250"/>'+
'</div>';
var bodyHTML = '<div>'+
'<h1>hello world</h1>'+
'</div>';
var html = styleHTML + headerHTML + bodyHTML
var test = new sn_pdfgeneratorutils.PDFGenerationAPI().convertToPDF(html, 'table_name', 'record_sys_id', 'pdfFileName', '');
Have I missed something?
Cheers
Seems legit code...
I haven''t used the @page :first before, so don't know if SN allows it...
Obviously the image name is case sensitive and I found that it wouldn't allow .JPG or .PNG but does allow .jpg and .png, so no uppercase extensions (no clue on why not though...)
I see you're not using a sys_pdf_generation_font_family - sys_id, perhaps having no fonts included has its effects as well?
Other that these I can't think of anything...
So after alot of testing, I got it to work by mistake. I added an extra value into the id property for the pageHeader element and for some bizarre reason the img element worked. I then just left a space in the id property's value instead and that was also acceptable.
<div id="pageHeader ">
Have no idea why, I thought it may have been because of the extra white space I had before the #pageHeader css
' #pageHeader { position: running(pageHeader) }' +
but still didn't work after i cleaned it up. Anyway, I'm happy to move on.
Sometimes its just enough that things work!
Still very strange though...
On this issue, finally needed this as well, so I added this to the CSS:
@bottom-right-corner { font-family: Arial; font-size: 10pt; content: counter(page) " / " counter(pages); }
Problem is, the pages counter has 1 page too many...
My document has 2 pages and it shows 1/3 and 2/3...
Ideas?
Is anyone aware of a way to add a Table of Contents to a generated PDF document?
hey, i've experimented a bit with this but haven't found a solution yet to dynamically map the links with page number
but you can build a dynamic overview with links without page numbers like this:
<a href="divId></a>
maybe it helps you a little bit otherwise i would also be very interested in a solution
Ohh that's a really good idea, I didn't even think of that. I think that will have to be the best option for now.
how can i bring the page number to the bottom of the page .. for me its printing at the top of the page
Sorry, is this code an include script? and is it called with a rule? please help, I need to create a pdf for a request article
Hi Samuel,
This is all in an include script indeed, I mainly call this function from an UI-action, using a GlideAjax call.
Cheers,
Chris
THANK YOU!! This has been a total life/job saver, much appreciated!
If you review my posted code it says:
'@bottom-right{ content: counter(page) " / " counter(pages); font-size:8pt; }' +
This should be within your @page section in your CSS.
(ps: counter(pages) isn't working for me, but the counter is just fine)
PDFGenerationAPI API | ServiceNow Developers - Rome
PDFGenerationAPI API | ServiceNow Developers - Quebec
Would you be able to provide an example of the UI action calling this? Do you use the standard GlideAjax calls?
Hi Ashley, I didn't put any variables in the example so any standard call would do.
We actually don't use ajax to call it, since its called from a widget server script and from other script includes.
How can I put a background image or watermark that appears on all pages except the first?
You need to create a different class on the first page, f.e.:
/* set background image per page */
.home-bg {
background: url(images/home-bg.jpg) no-repeat center center fixed;
}
.about-bg {
background: url(images/about.bg.jpg) no-repeat center center fixed;
}
.contact-bg {
background: url(images/contact-bg.jpg) no-repeat center center fixed;
}
For home page:
<html class="home-bg">
For about page:
<html class="about-bg">
For contact page:
<html class="contact-bg">
My html contains some information in Thai language. The API works fine for English and even for Chinese. But for Thai the convertToPDF function fails.
Below is the result log.
{"message":null,"request_id":"3f3b858d1b99c910bf3b415de54bcb03","status":"failure"}
Thank you for the article. When I convert my KB article using the sn_pdfgeneratorutils.PDFGenerationAPI API to PDF, the images in the KB article is missing. Any suggestions?
Issue is related to image not accessible without authentication. Any other suggestion? Cannot make the image public.
How did you end up solving the Times New Romain issue? We're having the same issue.
If the image is on the attachment table you have to get the attachment and convert it to base 64 before adding it to the HTML. You may have to replace your image tag in the HTML as it will already be there. It might be tricky finding the correct image tag and replacing it but there is an XML API that you can use that turns XML into a JS object. You can loop through your object to find and replace anything that contains the IMG tag with a base 64 version of the image.
var gsa = new GlideSysAttachment();
var agr = gsa.getAttachments('kb_knowledge', 'KBA SysID');
while (agr.next()) {
html = html.replace(
'<img ...>',
'<img src="data:image/png;base64, ' + gsa.getContentBase64(agr) + '"/>'
);
}
Does somebody know if the fontSysId is still a thing?
In the official documentation they have only 5 parameters.
https://developer.servicenow.com/dev.do#!/reference/api/quebec/server/sn_pdfgeneratorutils-namespace/PDFGenerationAPIBothAPI#P-convertToPDFWithHdrFtr_S_S_S_S_O
I guess it would use otherwise just the themes system font? Where would be the best way to add a new systemwide font?
Is anybody having trouble after the San Diego upgrade?
It seems like CSS 3 pages media are being ignored.
Any help?
Hey,
change the system property "com.snc.pdfgenerator.html2pdf.api.version" value to 1
I logged a HI ticket and got this response:
Heard back from our DEV team and they have identified this as a defect (PRB1575866) caused by one of the enhancements in San Diego release. Please refer below as a temporary relief for the issue while they continue to work on the defect.
============
We started working on this defect and identified that this issue is caused by one of the enhancements in SanDiego. The customer can get a temporary relief for the issue by setting value of system property "com.snc.pdfgenerator.html2pdf.api.version" to 1. Though customer won't be able to use TOC tag which is introduced with San Diego. PRB ID for this defect is DEF0298967.
============
Thank you both.
Could you please let us know when the defect is resolved?
In the old GeneralPDF API we had multiple HTML Wrapper functions to make that happen.
I see there is Document API available, but again that provides the function to add texts but not the HTML content
Any news about the defect?