@
- 一、準(zhǔn)備模板
-
1、創(chuàng)建模板文件
-
2、處理模板
- 2.1 處理普通文本
- 2.2 處理表格
- 2.3 處理圖片
- 二、項(xiàng)目代碼
- 1、引入依賴
- 2、生成代碼
-
2、處理模板
- 三、驗(yàn)證生成word
一、準(zhǔn)備模板
1、創(chuàng)建模板文件
首先先建立一個(gè)word文件,輸入模板內(nèi)容freemaker的內(nèi)容,下面是本次演示的word文件。
然后將word文件另存為 .xml
文件,然后再把文件后綴改成.ftl
。將項(xiàng)目的resource目錄下建立一個(gè)templates目錄(非必須步驟)將 模板文件放到templates目錄下
打開(kāi)模板文件按 Ctrl + Shift + L 將模板內(nèi)容格式化。
2、處理模板
2.1 處理普通文本
處理文本比較簡(jiǎn)單,將需要替換文本中直接用占位符 ${}
替換即可。
這里發(fā)現(xiàn)一個(gè)問(wèn)題因?yàn)橹霸趙ord格式時(shí)我就已經(jīng)替換了變量,但是在ftl變量卻被 拆分成多段了(見(jiàn)圖1)。但是這樣是freemaker是無(wú)法成功替換變量的,所以需要手動(dòng)處理成到一個(gè)段里(如圖2),關(guān)于這點(diǎn)實(shí)在太無(wú)語(yǔ)了,因?yàn)闆](méi)有找到比較好的處理辦法,只能手工處理,在實(shí)際的開(kāi)發(fā)工作中曾經(jīng)花了幾個(gè)小時(shí)來(lái)做這件事情。
圖1:
圖2
?
2.2 處理表格
如果模板里需要用變量填充表格,建議模板里的表格像word文件一樣建一個(gè)兩行的表格。在模板中<<w:tbl>> 表示一個(gè)表格 、<w: tr> 表示一行、<w: tc> 表示一列。因?yàn)镕reeMarker 是利用列表一行一行循環(huán)填充的,所以我們可以根據(jù)關(guān)鍵字找到<<w:tbl>>標(biāo)簽,因?yàn)榈谝粋€(gè) <w: tr>是表頭注意不要改到了,找到第二個(gè)<w: tr>在前后分別加上如下語(yǔ)句即可,后面的表格里后面的行<w: tr>需要?jiǎng)h掉,建議模板里的表格像word文件一樣建一個(gè)兩行的表格即可這樣就不用刪了:
<#list itemList as item>
</#list>
替換后的模板如下:
2.3 處理圖片
如果模板里需要用變量填充圖片,建議先在word文件里插入一張圖片,這樣在模板文件里找到<pkg:binaryData>標(biāo)簽直接里面把里面的圖片base64字符替換成變量即可,word里可以通過(guò)植入base64字符來(lái)展示圖片:
替換前:
替換后:
<pkg:binaryData>${image1}</pkg:binaryData>
到此模板已經(jīng)調(diào)整完成,接下來(lái)就可以開(kāi)始寫(xiě)代碼了。
二、項(xiàng)目代碼
1、引入依賴
在項(xiàng)目的pom文件里引入如下依賴
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
2、生成代碼
將圖片轉(zhuǎn)成Base64字符串的公共方法:
public static String getImageBase64Str(String imgFile) {
try( InputStream in = new FileInputStream(imgFile)) {
byte[] data = new byte[in.available()];
in.read(data);
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(data);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
根據(jù)模板文件生成word,主要生成的word的文件后綴必須是doc不能是docx,不然生成的文件無(wú)法打開(kāi)。
public static void crateWord(Map<String, Object> dataMap, String templatePath, String targetFile){
String path = templatePath.substring(0,templatePath.lastIndexOf("/"));
String templateName = templatePath.substring(templatePath.lastIndexOf("/") + 1);
try (FileOutputStream out = new FileOutputStream(targetFile);
Writer writer = new BufferedWriter(new OutputStreamWriter(out, "utf-8"))){
Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
configuration.setDefaultEncoding("utf-8");
configuration.setClassForTemplateLoading(FreeMakerTest.class, path);
//除了ClassForTemplateLoading外,另一種模板加載方式DirectoryForTemplateLoading,也可用
//ClassPathResource resource = new ClassPathResource(path);
//configuration.setDirectoryForTemplateLoading(resource.getFile());
//加載模板
Template template = configuration.getTemplate(templateName);
//渲染模板
template.process(dataMap, writer);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (TemplateException e) {
throw new RuntimeException(e);
}
}
三、驗(yàn)證生成word
新建的列表數(shù)據(jù)實(shí)體類(lèi):
public class Arrears{
private String name;
private Integer num;
private String endDay;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getNum() {
return num;
}
public void setNum(Integer num) {
this.num = num;
}
public String getEndDay() {
return endDay;
}
public void setEndDay(String endDay) {
this.endDay = endDay;
}
}
準(zhǔn)備模板填充數(shù)據(jù)
private static Map<String, Object> prepareParam(){
LocalDate currentDate = LocalDate.now();
LocalDate endDate = currentDate.plusYears(1L);
List<Arrears> arrearsList = new ArrayList<>();
arrearsList.add(new Arrears(){{setName("一頓老魏");setNum(1);setEndDay("三月內(nèi)");}});
arrearsList.add(new Arrears(){{setName("貴州大黃牛");setNum(1);setEndDay("一年內(nèi)");}});
arrearsList.add(new Arrears(){{setName("v我50");setNum(1);setEndDay("一月內(nèi)");}});
//填充所需要的數(shù)據(jù)
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("debtor", "陳有楚");
dataMap.put("nowYear", String.valueOf(currentDate.getYear()));
dataMap.put("nowMonth", String.valueOf(currentDate.getMonthValue()));
dataMap.put("nowDay", String.valueOf(currentDate.getDayOfMonth()));
dataMap.put("arrears", "一頓老魏、貴州大黃牛、v我50");
dataMap.put("endYear", String.valueOf(endDate.getYear()));
dataMap.put("endMonth", String.valueOf(endDate.getMonthValue()));
dataMap.put("endDay", String.valueOf(endDate.getDayOfMonth()));
dataMap.put("arrearsList", arrearsList);
dataMap.put("image1", getImageBase64Str("D:\\picture\\其他\\24-05-23-142418.png"));
dataMap.put("creditor", "知北游");
return dataMap;
}
測(cè)試代碼:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-538256.html
public static void main(String[] args) throws IOException {
//準(zhǔn)備參數(shù)
Map<String, Object> dataMap = prepareParam();
crateWord(dataMap,"/templates/qiantiao.ftl","D:\\test\\qiantiao.doc");
}
測(cè)試結(jié)果:文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-538256.html
到了這里,關(guān)于根據(jù)模板動(dòng)態(tài)生成word(一)使用freemarker生成word的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!