Marty Zigman

Conversations with Marty Zigman

Certified Administrator • ERP • SuiteCloud

Interrogating NetSuite’s Advanced PDF / HTML Templates

NetSuite Technical

Tags: , , ,

This article is relevant if you are seeking to get a good handle on NetSuite’s Advanced PDF / HTML template technology

Background

I wrote about the general framework about a year ago in this article: “How To: Leverage NetSuite’s Advanced PDF / HTML Generation Tools” .  That article offers a good over and references to documents to help you build new templates.

Since that time and as of this writing, NetSuite has announced a roadmap to push customers toward the Big Faceless Organization (BFO) Freemarker framework for generating HTML and PDF documents.  The technology is still considered “Beta” but it is clear NetSuite is making a significant investment.  In anticipation for a need to master this new technology, I wanted to produce a Freemarker template that can help all of us understand the underlying data that is being passed to us so we can better craft our specific templates used in the business.  Meaning, I want to go much deeper into the possibility of using these tools to unlock the power.

Locked Up Data Model

I want to be wrong about this.  But after spending about a half day trying everything I could, I have concluded that NetSuite is not supporting an important FreeMarker “Built In” called “keys”.  Essentially, when NetSuite provides us with a reference to the template data model such as “record”, we are supposed to know in advance the field name.  For example, if you want the date on the record, you would reference “${record.trandate}”.

That is fine and dandy, but it demands much hunt and pecking to get field names.  Sometimes, field names are not so obvious especially as you start to traverse NetSuite sublists.  I wanted to build a tree representation of all the data being passed to us so we can diagnose the data model and its contents to dramatically shorten the trial and error cycle required to build our templates.

Built in “Key” Lookup

NetSuite is not obligated to give us the Built-In “Key” lookup.   When NetSuite provide us data elements to work with, they are provided as Hashes.  The Hash is effectively a collection of name:value pairs commonly available in most object oriented development languages.  Sometimes these are called dictionaires because with the name, you can get its value or meaning.  In general, when you have a Hash, you can loop through all the elements if you have the “Keys”.  The Keys are a list of all the names located within the Hash.  This is perfect if we want to output every field name and its related value.  Imagine the time saved if you could spit out all the data NetSuite passes to us so we can see it in one place and perform cut-and-paste field name operations during our template development?

The Keys are available to us at the very top of the tree called the “data_model”.  I have produced a template that at least let’s us look at the names of all the hashes (record types) being passed to us.  From this, we can tell that the hashes are not case sensitive.  For example, NetSuite’s sample templates show us ${companyInformation}.  From my discovery work, ${companyinformation} works just as fine as well.

I suspect NetSuite is not providing us the Keys because it may reveal more data than what they want us to see and possibly breach security.   But really, just because something is obscure does not mean it is secure.

NetSuite Advanced PDF Inspection Template

This template is quite basic primarily because Keys support is limited.  Use it to inspect what record types are being passed to you.

<?xml version="1.0"?>
<!DOCTYPE pdf PUBLIC "-//big.faceless.org//report" "report-1.1.dtd">
<pdf>
<head></head>
<body>
<h2>Advanced PDF Template to Discover BFO Global Environment Information Passed from NetSuite</h2>
<h2>Crafted by Marty Zigman</h2>
<div><img src="https://www.prolecto.com/assets/footer/casual-cropped-marty-zigman-20121025-small.jpg"></img></div>
<div><img src="https://www.prolecto.com/assets/footer/prolecto_logo_360x41_2007.jpg"></img></div>
<p>Template Version: ${.version}</p>
<p>Template Name: ${.template_name}</p>
List (.data_model)
<table>
	<#assign keys = .data_model?keys>
	<#list keys as key>
		<tr>
			<td>Key: ${key}</td>
			<td>Value: ${.data_model[key]}</td>
		</tr>
	</#list>
</table>
List (.namespace)
<table>
	<#assign keys = .namespace?keys>
	<#list keys as key>
		<tr>
			<td>Key: ${key};</td>
		</tr>
	</#list>
</table>

List (.main)
<table>
	<#assign keys = .main?keys>
	<#list keys as key>
		<tr>
			<td>Key: ${key};</td>
		</tr>
	</#list>
</table>
</body>
</pdf>

NetSuite Enhancement Request

There is a NetSuite enhancement request for this capacity. Please vote for SuiteIdea: 296495 to help this enhancement get priority.  Once it is in place, I will develop a template that will enumerate all the field names and values so we all can enjoy.

Related Articles

We are committed to this space.  With some tools we built which are available to, all the data is now exposed.  See below articles most relevant for NetSuite users working to get more out of the Advanced PDF/HTML tools:

  1. How To: Leverage NetSuite’s Advanced PDF / HTML Generation Tools
  2. Supercharge NetSuite Advanced PDF/HTML Templates
  3. Solved: Custom NetSuite Item Fulfillment Ship Notifications
  4. Framework for Generating Custom NetSuite PDF Files

Marty Zigman LinkedIn

Marty Zigman

Holding three official certifications, Marty is widely recognized as a top NetSuite expert and leads a team of senior professionals at Prolecto Resources, Inc. A former Deloitte & Touche CPA and technology executive with CTO roles, he brings over 35 years of leadership in ERP, CRM, and eCommerce business systems. Contact Marty to engage directly.

BiographyYouTubeLinkedInX (Twitter)

39 thoughts on “Interrogating NetSuite’s Advanced PDF / HTML Templates

  1. An easy hack to get fields that are present for Freemarker is to append &xml=t to the transaction you are viewing. This doesn’t give you what you have available from company but gives most of what you can get from record.

    Reply
  2. Hi Marty, i want to create sales order pdf using suitelet. I wrote the code to do that, but the XML Parser in not parsing the Logic directives how to write those in script. pls help me.

    Reply
  3. Hi Marty
    I have clear the suite foundation exam and now preparing for Certified developer.
    Please let me which study material should I refer.
    Any specific Netsuite PDF, Video,Help topics.
    Thanks in advance.

    Reply
  4. Hi Marty,

    You mentioned you edit the XML in another editor and copy and paste it into the NetSuite interface.

    Our team has streamlined this by uploading all the templates to the File Cabinet and using the SuiteScript plugin for eclipse to edit straight in eclipse. We use imports in the NetSuite interface to load the template from the File Cabinet.

    This gives you the a) advantage of an easy workflow (e.g. ctrl + u automatically uploads to NetSuite so it’s as simple as pressing ctrl + u and refreshing the template to try any new changes) and b) the ability to use version control (e.g. git) to collaborate efficiently.

    Reply
  5. Hey Marty,

    Today I started to build my first Advanced PDF template for an invoice. All is fine except I need to show a line of text based on tax code. Now I can pull the tax code but when I do a compare it is never true:

    text to be shown here…

    If I do a != my text is shown. However, the value returned from taxcode on the line item shows VAT:Standard GB.

    Any thoughts or advice? And how can we reach the field ids from the line item on an invoice, is this possible?

    Many Thanks!

    Reply
  6. Marty,

    Great article. I was hoping there would be some way to pull out the various field IDs, but cannot get anywhere. I noticed on the advanced PDF pick tickets, there is no longer a column for the preferred bin of the item. I’ve tried numerous field names and cannot get anywhere. Do you have any ideas on how to go deeper into this? I know your article was published in 2014… I’ve tried record.item.binnumbers, nothing…I’ve even tried record.item.item.binnumbers which DOES get me to the bin sublist, but getting the preferred bin for the given location would be a mess of code!

    Reply
  7. Looks interesting. Right now we’re still using the non-Advanced PDF forms, which has a printable field for “Bin Numbers”. This is the only thing holding us back from using the new Advanced PDF pick tickets.

    Reply
  8. Hey Dan,

    We ended up creating a Suitelet to do this. It wasn’t easy, but it works well as we needed a way to print pick-pack tickets customized for each of our customers.

    Cheers,

    Mark

    Reply
  9. Thanks for the quick responses guys. I was hoping it was something obvious that I was missing, but unfortunately, that’s not the case. I’ll see if I can file something with NetSuite to get this back. For now, I think we’ll continue with the standard PDF templates.

    Thanks!

    Reply
  10. Hey Marty,

    I just reviewed the code really quick, and it appears we ended up using the OzLink custom fields, but I don’t see any new ones created. I’ll email you a screenshot of how this looks form wise on our end now.

    It has actually worked pretty well since we had discussed initially with you our problem.

    Cheers,

    Mark

    Reply
  11. Hi, Marty.

    I found this post very useful to find out the real data structure being passed on to the template. What I’m really struggling is to find out the correct syntax to enumerate the fields (for the record data, for example).

    Is this only a matter of using the correct syntax to get the second-level fields keys or is there another level of complexity I’m not aware of?

    Reply
  12. Hai sir i have one doubt i get the standard sublist from transaction record but i did’t get the custom sublist can you please help me using in freemarker advanced PDF

    Reply
  13. I would like to know if there is something similar for the E-Document Templates?
    I am trying to access custom fields of the client address, but I am not getting it: customer.address.field … For the XML Electronic Invoice.
    Thank you!

    Reply
  14. Thank Marty very helpful.

    Although one thing i’m struggling with is accessing the values of a saved search passed to the Advanced PDF via renderer.addSearchResults.

    As the search columns are Grouped or Summed i dont seem to be able to get at the data. Even though it knows the correct number of results when i do the list, but the key is empty.

    Key: ${key}

    Search data looks like this:-


    values: {
    "GROUP(item.upccode)": "5055956017850",

    Any help would be appreciated. 🙂

    Reply
  15. Have you by chance ever discovered a way to have elements render or not based on whether the final document output will be html or pdf? Some things I can solve by using inline attributes that override the inline style attribute since they are valid in xml but ignored in html but I would really like a way to have freemarker skip inclusion of elements I only want included if the document will ultimately be rendered as a pdf. There are many pdf only elements (shape tags, charts etc) that BFO supports and I would really prefer that code not be present when rendered as html. Any insight you might have on that front would be greatly appropriated. Thanks.

    Reply
  16. This template doesn’t work anymore, right?

    I got this error:

    The template cannot be printed due to the following errors: Error on line 18, column 36 in template. Detail… For “${…}” content: Expected a string or something automatically convertible to string (number, date or boolean), or “template output” , but this has evaluated to a method (wrapper: com.netledger.app.accounting.print.nsformat.NsFormatBooleanMethodModel): ==> .data_model[key] [in template “template” at line 18, column 38]

    Reply
  17. Thank you Marty for this article.

    One question. How do you append the Advanced PDF with a pdf from your computer c drive.

    I tried
    The code works with field_id as https://catalog.belden.com/techdata/EN/9207_techdata.pdf

    However when I wan to use a local pdf file with the field_id as C:\VIP.pdf it throws below error
    “Error reading external PDF from C:\VIP.pdf”

    Any help would be appreciated.

    Ani Raj

    Reply
  18. Thank you Marty,
    So it is either a file on Netsuite server or on a web address, but can’t be one a local drive. Got it, thanks

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *