anyone have any luck using the N/Render module to ...
# suitescript
p
anyone have any luck using the N/Render module to make multi-page PDF's from transactions?
e
What’s the specific challenge you have? I’ve used this successfully before:
render.transaction({ entityId: transactionId, printMode: render.PrintMode.PDF, formId: templateId });
where transacionId is the internal id of the transaction, and formId is the internal id of the custom form
what i found annoying is that we had to create a Custom Form on the transaction type and that form specifies the Advanced PDF/HTML Template. I’d rather have gone straight to the Advanced PDF Template directly. Not sure that’s possible…
this is from the documentation:
options.formId number optional The transaction form number
e
You can use the
<pbr/>
tag to insert page breaks wherever you'd like
p
awesome the render.transaction worked. Question though how do i use the <pbr/> tag if I am getting PDF file from the render.transaction?
e
that tag would be in your Advanced PDF/HTML Template, if you have one defined on your custom form
e
You can use the
<pbr/>
tag directly in the template to break pages there, and you can also use it if you are concatenating multiple transactions together into a single pdf
p
I guess that's the part i am missing is concatenating the PDF file objects returned by the render.transaction
e
There is some XML to be replaced in each one; like you ahve to strip out the header and html tags and then add your own, but I do something like:
Copy code
var transactionIds = [100, 123, 45556, 78923];

var pdfBody = transactionIds.map(toPdf)
  .map(removeHeader)
  .join("<pbr/>");

var pdfContent = pdfHeader + pdfBody + pdfFooter;
The map transformers can of course be combined into a single function, but I wanted to illustrate the steps
p
Okay, i am starting to get it now. So the toPdf function generates the PDF file from each of the transactions, than also removes the header, than you join each of those array elements with the <pbr /> to page break. The the pdfHeader and pdfFooter are static values.
On the toPDF fucnction how are you getting the XML for it?
e
Yep you've got the concepts
Copy code
function toPDF(id) {
        var tmpl = render.create();
        tmpl.setTemplateById({id: this});
        tmpl.addRecord({
            templateName: "record",
            record: r.load({type: "customrecord_blah", id: id})
        });
        var contents = tmpl.renderAsString()
            .replace(PDF_HEADER, "")
            .replace(PDF_FOOTER, "");
        return contents;
    }
probably the key part is the
renderAsString()
call
In that code
this
is the template ID
so it's actually invoked as
.map(toPDF, templateId)
that's an only slightly doctored working example btw
pulled from some recent code
p
is the pdfHeader the "<?xml version="1.0"?><!DOCTYPE pdf PUBLIC "-//big.faceless.org//report" "report-1.1.dtd">" and the footer the "</pdfset>"
I get the error "ReferenceError: "PDF_HEADER" is not defined". BTW Eric thank you so much for the help so far
e
Yeah if you haven't defined a
PDF_HEADER
module variable, that's what I'd expect
You can either determine the appropriate values for the two variables in that fn, or you can remove that portion of the fn, but I wouldn't expect a straight copy and paste to just work in your environmnet
e
@erictgrubaugh, don’t mean to confuse things here but couldn’t you just combine pdfs using pdfset? I have an example somewhere i’m sure, but can’t locate it at the moment
p
got you Eric. I removed those that portion of the function and reduced the array to one element to test and i got the below error.
Copy code
{
  "type": "error.SuiteScriptError",
  "name": "USER_ERROR",
  "message": "Error Parsing XML: The reference to entity \"c\" must end with the ';' delimiter.",
  "stack": [
    "createError(N/error)",
    "onRequest(/SuiteScripts/Somnomed-Prod/sm_sl_mass_fulfill_so.js:192)"
  ],
  "cause": {
    "type": "internal error",
    "code": "USER_ERROR",
    "details": "Error Parsing XML: The reference to entity \"c\" must end with the ';' delimiter.",
    "userEvent": null,
    "stackTrace": [
      "createError(N/error)",
      "onRequest(/SuiteScripts/Somnomed-Prod/sm_sl_mass_fulfill_so.js:192)"
    ],
    "notifyOff": false
  },
  "id": "",
  "notifyOff": false,
  "userFacing": false
}
e
@ec You can do that as well, but then you have less control over how the pdfs are joined, and you cannot set up your own header/footer
so while you could join them with nothing, or with a
<pbr/>
you could also do something much more complicated/fancy with a
<div>
or whatever other HTML you can come up with
<pdfset>
does not let you do that
✔️ 1