之前介紹過 Advanced PDF 的標籤之後,不知道大家有沒有辦法活用在公司的樣板中呢?這次會用四個範例來介紹一個十分好用的 Advanced PDF 標籤: <#include>。
學習 Advanced PDF <#assign> & <#if condition>:
2 個最重要的 NetSuite Advanced PDF tag:<#assign> & <#if condition>
Table of Contents
標籤介紹
FreeMarker 的 <#include> 標籤用來將一個外部文件插入到主模板中。在這個標籤的加持下,我們就可以插入一個 Suitelet 來顯示我們需要的內容。
<#include "URL" /> 使用範例
#1 建立一個 Sample Advanced PDF,參考程式如下:
<?xml version="1.0"?><!DOCTYPE pdf PUBLIC "-//big.faceless.org//report" "report-1.1.dtd">
<pdf>
<body header-height="11%" footer-height="30pt" padding="0.5in 0.5in 0.5in 0.5in" size="A4">
<h1>Original Advanced PDF content</h1>
</body>
</pdf> 在這個 Advanced PDF 列印出來的樣子會只有一行字。如下顯示:

#2 建立一個 Suitelet 參考程式如下:
/**
* @NApiVersion 2.1
* @NScriptType Suitelet
*/
define([], () => {
const onRequest = (scriptContext) => {
scriptContext.response.write("HELLO FROM SUITELET");
}
return { onRequest }
}); 並且將 Suitelet 部署到目標帳號,並且設定 Available without login,取得 External URL 網址。

#3 修改 Advanced PDF,新增 <#include>標籤
<?xml version="1.0"?><!DOCTYPE pdf PUBLIC "-//big.faceless.org//report" "report-1.1.dtd">
<pdf>
<body header-height="11%" footer-height="30pt" padding="0.5in 0.5in 0.5in 0.5in" size="A4">
<h1>Original Advanced PDF content</h1>
<#include "URL_FROM_SUITELET">
</body>
</pdf> #4 結果預覽,可以看到 HELLO FROM SUITELET 的文字出現,就表示我們可以用 <#include> 這個標籤插入客製化的訊息

進階範例:回傳變數
<#include> 的用法之後,我們就可以做一些進階操作,接下來讓我們修改一下 Suitelet。 /**
* @NApiVersion 2.1
* @NScriptType Suitelet
*/
define([], () => {
const onRequest = (scriptContext) => {
scriptContext.response.write("<#assign current_number = 10 />");
}
return { onRequest }
}); <?xml version="1.0"?><!DOCTYPE pdf PUBLIC "-//big.faceless.org//report" "report-1.1.dtd">
<pdf>
<body header-height="11%" footer-height="30pt" padding="0.5in 0.5in 0.5in 0.5in" size="A4">
<h1>Original Advanced PDF content</h1>
<#include "URL_FROM_SUITELET">
<h2>${current_number}</h2>
</body>
</pdf> 頁面成果:

在這個範例裡面,我們修改了 Suitelet 的回傳值,改為 <#assign current_number = 10 />。
在上一篇教學文章裡面有提到<assign />是 Advanced PDF 裡面用來宣告變數的標籤,在這邊我們可以直接回傳之後並且顯示在 Advanced PDF 裡面。
進階範例:Advanced PDF 操作變數
<?xml version="1.0"?><!DOCTYPE pdf PUBLIC "-//big.faceless.org//report" "report-1.1.dtd">
<pdf>
<body header-height="11%" footer-height="30pt" padding="0.5in 0.5in 0.5in 0.5in" size="A4">
<h1>Original Advanced PDF content</h1>
<#include "URL_FROM_SUITELET">
<h2>${current_number}</h2>
<#assign current_number += 10>
<h2>${current_number}</h2>
</body>
</pdf> 成果如下:

進階範例:帶 URL Parameter 的請求
繼續用同個 Advanced PDF 做示範:
<?xml version="1.0"?><!DOCTYPE pdf PUBLIC "-//big.faceless.org//report" "report-1.1.dtd">
<pdf>
<body header-height="11%" footer-height="30pt" padding="0.5in 0.5in 0.5in 0.5in" size="A4">
<h1>Original Advanced PDF content</h1>
<#assign so='123' />
<#include "URL_FROM_SUITELET&soId=" + so>
<h2>${current_number}</h2>
<#assign current_number += 10>
<h2>${current_number}</h2>
</body>
</pdf> 接下來修改 Suitelet,透過 scriptContext.request.parameter 取得 URL Parameter。
/**
* @NApiVersion 2.1
* @NScriptType Suitelet
*/
define([], () => {
const onRequest = (scriptContext) => {
scriptContext.response.write("<#assign current_number = 10 />");
log.debug({title: 'parameter from advanced pdf', details: scriptContext.request.parameters})
}
return { onRequest }
}); 成果在 NetSuite 顯示如下,可以看到在 Log 窗內有抓到 soId: 123,這樣子就可以在 Suitelet 裡面進行複雜的操作了!

結語
<#include>這個標籤再遇到複雜計算的時候,會比起在 Advanced PDF 內實現容易得多,例如:當我們想要印 Sales Order 但又必須取得 Invoice 上的特定欄位的時候,也可以使用。
但有幾點需要注意:
- 因為是 Available without login,所以理論上所有人都可以 Access 這段 URL,因此在 URL 裡面最好有一些驗證,比方說要回傳特定的字串才執行
- Suitelet 內只引入需要的 Function,並且限制執行角色(role)
- Advanced PDF 內,應該要檢查 Suitelet 回傳的字串,比方說
<#if current_number??>用來確保 Advanced PDF 沒有錯誤
今天的 Advanced PDF 教學就到這邊,下一篇文章會來分享:如果 Suitelet 回傳的是一個 JSON 或是 一個陣列的話,Advanced PDF 有辦法解析嗎?
若你在實作過程中遇到問題,我們有提供付費的技術教學服務,歡迎來信洽詢。
專注於系統客製化、系統維運與系統優化領域的團隊。致力於讓使用者系統變好用!
NetSuite Record Export 已在Google Chrome Web Store上架,歡迎任何反饋。
合作: info@inzaghi-corp.com
