[Java] Poi-ti根據word 模板template 生成新的word 文檔 替換文字
製作動機
因為工作上遇到根據給固定的Word 模板生成相關報告的需求,選用Poi-ti主要是因為該API算是在原Apache POI的Word模板引擎升級版,非常易用.
Poi-tl 簡介
Poi-tl是Word模板引擎透過標籤替換快速產生word 文件
以下為核心api code
XWPFTemplate template = XWPFTemplate.compile("~/file.docx").render(datas);
所有的語法結構都是以{{ 開始,以}} 結束
實作checklist
- 引入依賴
- 準備一份Word模板文件
- 調用Poi-ti-Api
Getting Started
1.1引入Maven 依賴
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.10.0</version>
</dependency>
1.2使用Gradle則是
compile group: 'com.deepoove', name: 'poi-tl', version: '1.10.0'
2.1準備一份Word模板文件
如下預期能頒發一張由特殊樣式圖片、姓名、日期構成的證書獎狀
2.2製作模板,包含標籤 {{標籤替換}}
poi是一款透過標籤替換達到快速產生word
採用TDO模式:Template + data-model = output
因此我們需要先製作模板
所有的標籤都是以{{
開頭,以}}
結尾,內容則是你想替換的變數自訂
新建文檔certificate.docx
,包含文本{{Name}} ,{{year}},{{month}} 等等
3.1替换文字與使用Poi-ti-核心api
定義map完成指定標籤替換
//處理日期轉換成民國Calendar c = Calendar.getInstance();c.setTimeInMillis(System.currentTimeMillis());int year = c.get(Calendar.YEAR) - 1911;int month = c.get(Calendar.MONTH) + 1;int day = c.get(Calendar.DAY_OF_MONTH);System.out.print("民國" + year + "年");System.out.print(month + "月");System.out.println(day + "日");
// 用一個map將標籤替換指定文字Map<String, String> testMap = new HashMap<String, String>();testMap.put("Name", "王大大");testMap.put("year", Integer.toString(year));testMap.put("month", Integer.toString(month));testMap.put("day", Integer.toString(day));testMap.put("minister", "Kumamon");
接著調用核心api
替換對應文字
XWPFTemplate template = XWPFTemplate.compile(templatePath).render(testMap);
寫出檔案至我的桌面
template.writeAndClose(new FileOutputStream("/Users/guowei/Desktop/我的證書.docx"));
可以在桌面看到產生出的 我的證書.docx
並且姓名 日期 部長皆以替換成功
完成!
了解怎麼使用poi-ti 後那我們就可以應用他透過替換快速產生word 文件
製作出可讓使用者輸入內容的動態產生證書的網頁
製作可產生自定義證書 網站
前端
設定post到generateCertificate
<form method="POST" action="/generateCertificate">
<div class="input-group">
<input class="input--style-1" type="text" placeholder="姓名"
name="name">
</div>
<div class="input-group">
<input class="input--style-1" type="text" placeholder="部長"
name="minister">
</div>
<div class="input-group">
<input class="input--style-1" type="text" placeholder="證書名稱"
name="certificationName">
</div>
<div class="p-t-20">
<button class="btn btn--radius btn--green" type="submit">產生</button>
</div>
</form>
下載檔案程式Controller在調用這隻
注意點
1.是classpath in jar 讀取時不可使用getfile
2.Safai瀏覽器中文字變亂碼須轉換
可以參考這邊
//替換寫入並下載檔案
public static void downloadReportFile(String templatePath, String fileName, Map<String, String> replaceMap,
HttpServletResponse response, HttpServletRequest request) throws UnsupportedEncodingException {System.out.println("進入下載");XWPFDocument document = null;InputStream in = null;// 生成新的word
response.reset();
response.setContentType("applicatoin/octet-stream");ByteArrayOutputStream ostream = new ByteArrayOutputStream();
OutputStream os = null;String userAgent = request.getHeader("User-Agent").toLowerCase();
System.out.println(userAgent);if (userAgent.contains("safari")) {
// 處理safari中文字檔名造成亂碼
System.out.println("進到safari");
String safariFileName = new String(fileName.getBytes("utf-8"), "ISO-8859-1");// fileName.getBytes("UTF-8")處理safari的亂碼問題
response.addHeader("Content-Disposition", "attachment; filename=" + safariFileName);} else {
response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
}try {System.out.println("執行生成Word");// 會使用Classpath原因:因為我們會包成jar檔部署到公有雲,打包後Spring會去訪問系統的路徑,但無法訪問JAR中的路徑InputStream()
in = new ClassPathResource(templatePath).getInputStream();
// 替換標籤文字
XWPFTemplate template = XWPFTemplate.compile(in).render(replaceMap);
System.out.println("替換完畢");
os = response.getOutputStream();
template.writeAndClose(os);// 輸出到response
os.write(ostream.toByteArray());in.close();
os.close();
ostream.close();} catch (IOException e) {
e.printStackTrace();
} finally {
try {if (in != null) {
in.close();
}
if (document != null) {
document.close();
}
if (os != null) {
os.close();
}
if (ostream != null) {
ostream.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
最後複習一下
GKE部署
此次我們使用JIB 幫助我們更快的打包image
mvn clean install jib:build
這樣就把我們的image推送到dockerhub了
複習K8s文件撰寫
deployment.yaml
deployment.yamlapiVersion: apps/v1
kind: Deployment
metadata:
name: wordutil-deployment
labels:
app: poi-tl-demo
spec:
replicas: 1
selector:
matchLabels:
app: wordutil
template:
metadata:
labels:
app: wordutil
spec:
containers:
- name: wordutil
image: huway0310/wordutil:0.0.1-SNAPSHOT
env:
- name: "PORT"
value: "8080"service.yamlapiVersion: v1
kind: Service
metadata:
name: wordutil
spec:
type: LoadBalancer
selector:
app: wordutil
ports:
- protocol: TCP
port: 60000
targetPort: 8080
部署可以參考這邊
程式源碼
希望這篇文章能夠幫助到你(妳)
如有錯誤指正
I hope you found this guide helpful. If not, then please let me know either in the comments below, I’m Albert