Expand your SuiteScript skills in the Sustainable SuiteScript community for NetSuite developers.

Render a Record as a PDF from a Template in SuiteScript

Created: February 5, 2024

This is a sample chapter adapted from the "Rendering PDFs with SuiteScript 2.1" Cookbook, part of the SuiteScript by Example series.

SuiteScript's N/render module allows us to specify custom XML and transform it into a PDF, but it's extremely clunky to manage XML within a string. Trying to write and manage our own XML to display all the pertinent data for multiple Record types would be unwieldy.

Plus, NetSuite already has a robust PDF Template system.

How about we leverage that from our SuiteScript instead?

N/render is Server-Side Only

Before we can get to rendering shiny PDFs, there's a little setup work to do first. PDFs can only be rendered in server-side scripts, meaning we can't drop code in the browser console and expect it to work.

Instead, we'll build a Suitelet that will render our PDFs for us.

We'll start by building a custom module file. This is where we'll be adding and changing the code from the upcoming examples:

/**
 * Custom module for executing N/render cookbook examples
 *
 * @NApiVersion 2.1
 * @NModuleScope SameAccount
 *
 * @author Eric T Grubaugh <eric@stoic.software> (https://stoic.software/)
 */
define(['N/render'], (render) => {
  const renderPdf = (response) => {
    // This is where our example code will go
  }

  return { renderPdf }
})
  1. Create a folder in the File Cabinet at /SuiteScripts/render-pdf-cookbook/
  2. Upload the above source code into the new folder in a file named render-cookbook.js.
  3. From now on, I will refer to this file as the "render-cookbook module".

Next:

/**
 * Suitelet for testing PDF rendering
 *
 * @NApiVersion 2.1
 * @NModuleScope SameAccount
 * @NScriptType Suitelet
 */
define(['./render-cookbook', 'N/https'], (pdfCookbook, https) => {
  /** @see https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_4407987288.html */
  const onRequest = (context) => {
    log.audit({ title: `${context.request.method} request received` })

    // Ignore POST requests
    if (context.request.method !== https.Method.GET) {
      return
    }

    pdfCookbook.renderPdf(context.response)

    log.audit({ title: 'Request complete.' })
  }

  return { onRequest }
})
  1. Use the above source code to create a second file in the same folder as before.
  2. Use this second file to create a new Suitelet named Render a PDF.
  3. Create a Deployment for the Suitelet; leave it in Testing status.
  4. On the Deployment, add a new Link in the Links sublist. Locate it somewhere accessible to the Role you'll be using to test the examples in this book. For me, using the Administrator Role, I chose Classic Center > Setup > Custom > Render a PDF.

Suitelet Deployment settings

⚠️ If either of these code files is named differently or is not in the same folder, you will likely receive MODULE_NOT_FOUND errors when attempting to access the Suitelet.

This Suitelet is our test runner for working with files. Whenever we need to test one of our code examples, we access the link for the Suitelet in NetSuite's main navigation, and we can monitor the resulting Execution Logs on the Suitelet record.

For the remainder of the article, you should not need to make any modifications to the Suitelet or its source code.

Rendering a Transaction as a PDF

Replace the renderPdf function in the render-cookbook module as follows:

const renderPdf = (response) => {
  const pdf = render.transaction({
    entityId: 1280,
    formId: 71
  })

  response.writeFile({ file: pdf, isInline: false })
}

This will result in something like:

Transaction rendered as PDF with Advanced Template

when you navigate to the Suitelet you created previously.

render.transaction()

The N/render module gives us several methods for leveraging NetSuite's Advanced PDF/HTML Template system. Here, we demonstrate the transaction() method's ability to render a Transaction record using the PDF Templates specified on the Transaction Form.

const pdf = render.transaction({
  entityId: 1280,
  formId: 71
})

The entityId is - despite the name - actually the internal ID of the Transaction record we'd like to render. The formId is the numeric internal ID of the Transaction Form to start from.

In this specific example, 1280 is the internal ID of a Quote/Estimate record, and 71 is the internal ID of the Standard Quote Transaction Form.

Importantly, formId is not the ID of a specific PDF Template. Instead, NetSuite inspects the Transaction Form you've selected, then uses the Print Template selected there.

Print Template field on custom form

Refresh the Suitelet's page, and you should see your transaction PDF form.

By default, transaction() and its sibling methods will print the record in either PDF or HTML format, depending on the User or the Company Preference for PRINT USING HTML. You can force the printing mode to one or the other by using the printMode option of each method and the render.PrintMode enumeration

Rendering other Record Types

The sibling methods for transaction() within N/render are:

All of these are convenience methods, abstracting the TemplateRenderer Object and returning the File instance for the PDF directly.

These methods all behave similarly, but I leave researching the specifics of each as an exercise for you.