只使用freemaker生成簡單的word文檔很容易,但是當word文檔需要插入動態圖片,帶循環數據,且含有富文本時解決起來相對比較復雜,但是使用Xdocreport可以輕易解決。
Xdocreport既可以實現文檔填充也可以實現文檔轉換,此處只介紹其文檔填充功能。
步驟:
1.制作模板
以以下文檔為例
?會議內容為一段富文本
我們需要在變量替換的位置通過快捷鍵Ctrl+F9 或 工具欄“插入”->“文檔部件或文本”->“域”
遇到需要循環的位置
在第一列的里
1.在第一個單元格設置域 "@before-row[#list userList as user]"
2.緊接著后面繼續設置域 @after-row[/#list]
3.在1和2兩個域之間設置普通的list里的元素的域
注意:
1.創建一個普通域值后,可以直接復制,但是需要右鍵編輯域修改域的名字.
2.word里有的域值,但是我代碼里直接沒傳,代碼運行就會報錯,代碼給這個域值傳null,運行也會報錯.
3.word里沒有的域值,我代碼里傳了,word僅僅是不會顯示這個值,并不會報錯.
4.測試得知:如果想要在List里一個單元格里填兩個變量,那么你在單元格里創建完一個變量域后,這個單元格的第二個變量域來源必須是復制第一個變量域, 不能自己再新建一個域, 會報錯的.
5.在List里創建完一個單元格里的變量域,再創建第二個單元格里的變量域時,你復制第一個單元格的變量域也好,還是自己再新建一個變量域也好,都可以,都不會報錯.
遇到圖片,先插入一張圖片,再為圖片添加書簽
?這樣模板就制作完成,不需要保存為xml,ftl。直接使用doc或者docx后綴即可
2.代碼實現
引入依賴
<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.1</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.1</version></dependency><dependency><groupId>org.jxls</groupId><artifactId>jxls</artifactId><version>2.6.0</version><exclusions><exclusion><groupId>ch.qos.logback</groupId><artifactId>logback-core</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.jxls</groupId><artifactId>jxls-poi</artifactId><version>1.2.0</version></dependency><dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>fr.opensagres.xdocreport.core</artifactId><version>2.0.2</version></dependency><dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>fr.opensagres.xdocreport.document</artifactId><version>2.0.2</version></dependency><dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>fr.opensagres.xdocreport.template</artifactId><version>2.0.2</version></dependency><dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>fr.opensagres.xdocreport.document.docx</artifactId><version>2.0.2</version></dependency><dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>fr.opensagres.xdocreport.template.freemarker</artifactId><version>2.0.2</version></dependency>
上代碼
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {private String xh;private String bumen;private String name;private String age;private ByteArrayImageProvider touxiang;}
@RestController
@RequestMapping("order/")
@Slf4j
public class OneController {@GetMapping("/bb")public void createXdocreport(HttpServletResponse response) throws IOException {InputStream inputStream = null;ServletOutputStream outputStream = response.getOutputStream();try {//讀取模板 inputStream = new FileInputStream("F:\\Desktop\\aa.docx");//注冊xdocreport實例并加載FreeMarker模版引擎IXDocReport report = XDocReportRegistry.getRegistry().loadReport(inputStream, TemplateEngineKind.Freemarker);// 設置特殊字段FieldsMetadata metadata = report.createFieldsMetadata();metadata.addFieldAsTextStyling("content", SyntaxKind.Html);//富文本metadata.addFieldAsImage("touxiang", "user.touxiang", NullImageBehaviour.RemoveImageTemplate);//圖片metadata.addFieldAsImage("xiangzheng","xiangzheng", NullImageBehaviour.RemoveImageTemplate);//圖片report.setFieldsMetadata(metadata);// 創建內容-text為模版中對應都變量名稱String content = "<p>我在這里放了一段富文本</p>" +"<p>我準備測試富文本的處理</p>";content = HtmlUtils.htmlUnescape(content);IContext context = report.createContext();//放普通字段context.put("name", "年終總結大會");context.put("time", "2021年3月26日");//放富文本context.put("content", content);//放list內容,其中包括放入圖片流InputStream p1 = new FileInputStream(new File("F:\\Desktop\\風靈月影.png"));InputStream p2 = new FileInputStream(new File("F:\\Desktop\\孤島5.png"));List<User> users = Arrays.asList(new User("1", "市場部", "張三", "33", new ByteArrayImageProvider(p1)),new User("2", "設計部", "李四", "40", new ByteArrayImageProvider(p2)));context.put("userList", users);//放入單獨的圖片File file = new File("F:\\Desktop\\孤島6.png");FileImageProvider xiangzheng = new FileImageProvider(file);context.put("xiangzheng",xiangzheng);// 生成文件,瀏覽器訪問可以直接下載.response.setCharacterEncoding("utf-8");response.setContentType("application/msword");String fileName = "warning_task.docx";response.setHeader("Content-Disposition", "attachment;filename=".concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));report.process(context, outputStream);} catch (Exception e) {log.info("生成紀要文件發生異常:<{}>", e.getMessage());}finally {if(inputStream != null){inputStream.close();}}}}
?最后瀏覽器下載的結果
完成