Editor Tips & Tricks

Change layout size (A4, A5, Landscape etc.)

The layout format used is set by the size attribute in the code and is most commonly set to "A4" for the entire layout. However, if you would like to create a layout that is in A4-landscape format for example it is an easy fix.

The size attribute is by default set to "A4" in Layouts and is part of the <body>. If you want the entire layout in another format you can change it there, e.g. to "A4-landscape".

If you want to add only one page in another size you can combine the tag for pagebreak <pbr/> and define the format for the next page using the size attribute. See image on the left.

Read more about the size attribute in the BFO documentation.

Print the Currency Symbol instead of Currency Code

When retrieving data from both records and searches, NetSuite will return the currency code (e.g. USD) and not the currency symbol (e.g. $).

Layouts has a predefined CURRENCY_SYMBOL tab library available in the context menu in the editor. From there you can find the appropriate tag for the currency that you wish to display. The tag ${CURRENCY_SYMBOL.GBP} for example would be displayed as ÂŁ when creating the PDF.

If you want to dynamically print the currency symbol based on your dataset result you can simply replace the .CURRENCYCODE with your dataset tag placed with [ ], for example ${CURRENCY_SYMBOL[TrxObj.Currency]}. Please note that you should not include ${} within the [ ].

Working with URLs in the code - Ampersands (&'s)

If you add urls directly in your code editor (for example when referencing a specific record or file (image or font file) the url may contain one or several ampersands (&). Since this character is a special character in HTML and XML you should replace it with the HTML entity for the ampersand (&) which is &amp; in order for the url to work.

Add password protection to your created PDF

If you want your PDF to be password protected so that the recipient only can view the PDF by first entering a password, you can easily accomplish this directly in the editor. By adding a <meta> tag with the name "password", the password you enter in the value field most be entered before the PDF can be fully visible.

See line 8 in below example.

Tables and page breaks

If you have a saved search that you want to display in a <table> in your PDF you can sometimes face the challenge of the table stretching over more than one page in the rendered PDF. By using the <thead>, <tbody> and <tfoot> elements in your table, your table headers (thead) and table footer (tfoot) if used will be repeated for each new page that contains a part of your table. If you do not specify any of these groups, any <tr> element that you directly add to the the table will be automatically added to the <tbody>.

In the below examples, the first example shows a table including all three elements. This structure will automatically handle the page-break-inside challenge. The <tfoot> element is not always used as you quite often only want to include column headers <thead> and your results <tbody>.

Example 2 and 3 will be treated the same and would not automatically display the column headers (<th> elements in this example) on each new page.

(1) Table with THEAD, TBODY and TFOOT

<table>
<thead>
<tr><th></th></tr>
</thead>
<tbody>
<tr><td></td></tr>
...
more rows
</tbody>
<
tfoot>
<tr><td></td></tr>
</tfoot>

</table>

(2) Table with THEAD, TBODY and TFOOT

<table>
<tr><th></th></tr>
<tr><td></td></tr>
... more rows
</table>


(3) Table with THEAD, TBODY and TFOOT

<table>
<tbody>

<tr><th></th></tr>
<tr><td></td></tr>

... more rows
</tbody>
</table>



If you have a table in which you do not want to allow a page break (for example if you have a several tables on the same page and if the last one cannot be fully displayed on the same page you want it to be displayed on the next page) you can use the <page-break-inside> attribute. The attributes takes two values: "auto" and "avoid". The default value is "auto". See example below. Other sometimes useful attributes are <page-break-before> and <page-break-after>. Read more about these attributes in the BFO HTML manual.


<table page-break-inside="avoid">

<tr>

<td>Column 1</td>

<td>Column 2</td>

</tr>

<tr>

<td>Column 1</td>

<td>Column 2</td>

</tr>

</table>


Format strings into number

If you have numerical values added to your code and you want to do calculations directly in your layout, you can use FreeMarker to format the strings into numbers. All data is initially added as strings which is why you need to format your data before running you calculations.

Read more about this and related topics in the FreeMarker manual, for example Built-ins for strings and Built-ins for numbers.


<!-- Our value will begin as a string ("") -->


<#assign myNumber = "15.00">


<!-- Add ?number to make it into a numerical value that can be used in your calculations -->


${myNumber?number}


Add custom FreeMarker functions

To make the code more efficient when adding FreeMarker logic, you can create your own functions and include in your code. In the Editor there is a separate tab called "FUNCTIONS" added for this purpose.

The below example is a function that calculates the percentual ratio between the previous value and the current value. If I do the same calculation multiple times I can use this function and call the function using a FreeMarker and include my values, for example ${ratioPct(15, 20)}.

<#function ratioPct prev curr>
<#if prev?has_content && curr?has_content>

<#assign ratio = (curr/prev*100-100)>

<#return (ratio?string["0"])+"%">

<#else>

<#return "N/A">

</#if>

</#function>

Remove or add decimals from percentage values in dataset

All data from you datasets are initially added to the editor as strings. Thus, if you have a percentage value added from a search for example you must add some FreeMarker if you want to remove or add decimals. The below code is a breakdown explaining step by step. However, when printing the value in the code you only need to add the code from the last row and replace the myPct variable with the variable in your code.

Read more about this and related topics in the FreeMarker manual, for example Built-ins for strings and Built-ins for numbers.

Our example: We have a percentage value = "40.00%" and we want to remove the two decimals.

<!-- Our value will begin as a string ("") -->


<#assign myPct = "40.00%">


<!-- Code Breakdown step 1: As our value is a string we can start by removing the "%" using the remove_ending method. -->


${myPct?remove_ending("%")}


<!-- Code Breakdown step 2: Our value is now "40.00". Now we format our value into a number using the number format. -->


${myPct?remove_ending("%")?number}


<!-- Code Breakdown step 3: Our value is now 40.00. To set a fixed number of decimals we must format it as a string again. -->


${myPct?remove_ending("%")?number?string["0"]}


<!-- The inclusion of ["0"] allows us to set the number of decimals. [0.#] would give us 1 decimal, [0.##] 2 decimals etc. -->


<!-- The final step is to add the "%" again. -->


${myPct?remove_ending("%")?number?string["0"]} %

Adding images

Images are not a specific dataset type and are usually added from your base record or using Search / Custom Label Search datasets.

Images can be embedded in your PDFs using the HTML <img> tag. The tag has some useful attributes:

  • src: Mandatory. Should reference the url for the image. The url could either be hard-coded directly in the tag or be dynamically referenced using the datasets added to the layout. Please note that images stored in NetSuite must be set to Available without login in order for them to be displayed properly.

  • alt: The alternate text that will be displayed in case the image cannot be displayed properly.

  • width: See next section about aspect ratio of images.

  • height: See next section about aspect ratio of images.

Example:

<img src="${mySearch[0].image}" alt="User image" />

The image's size and other properties can be further adjusted via the HTML and CSS code in the editor if needed.

How you add the image url to your PDF depends on whether you are using the dataset type Record or Search/Custom Label Search.

From Base record:

If the field type is Document or if the field type is List/record and the fieldid contains the word "image", the dataset will look for the url and include in your dataset. To print the image's url you add "@url" at the end of your FreeMarker tag. Example:

<img src="${myBaseRecord.custentity_image@url}" alt="User image" />

Useful tips:

  • If you have a document or image field on your base record and it contains "image" in its field id, the image will be available in your dataset automatically.

From Search:

The data added in the search should be the url of the image. If you have a document type field on your searched record, you can simply add that field and the url will automatically be what is included.

<img src="${mySearch[0}.custentity_image}" alt="User image" />

Keeping the aspect ratio of image

In the <img> element you can choose to set the width and height attributes if you want your image to have a certain size. However, if you do not know the aspect ratio of the image a fixed width and height could result in your image being either stretched or compressed.

For the search and custom label search dataset types* you get two additional parameters for all image fields, namely yourImageField@width and yourImageField@height. With this information and FreeMarker you can easily add code to keep the aspect ratio of your images. You can choose to either set a fixed width and the height will be automatically calculated or vice versa. Below example shows how the code can look like when we have a fixed height for an image. (*This is not yet supported for dataset type Record)

As the below code illustrates we used the known values of imgHeight, @width and @height to calculate our imgWidth.


<#assign imgHeight=70 />

<#assign imgWidth = imgHeight * MacroInfo[0].custrecord_sclmi_image1@width / MacroInfo[0].custrecord_sclmi_image1@height />


<img src="${MacroInfo[0].custrecord_sclmi_image1}" width="${imgWidth}px" height="${imgHeight}px" />