快捷搜索:  汽车  科技

java 模板文件生成word文件(Java根据Freemarker模板生成Word文件)

java 模板文件生成word文件(Java根据Freemarker模板生成Word文件)2. 代码实现4、设置模板参数(变量/占位符)3、用文本编辑器打开.ftl文件,将内容复制出来,格式化一下,再覆盖原来的内容(PS:格式化一下是为了方便查找并设置变量/占位符,当然设置好模板参数变量以后可以再压缩后再写会.ftl文件)另外,强烈不建议在word文件中去编辑设置模板变量,因为.docx文件在另存为.xml文件后,原先好好的一个变量可能就被拆开了,建议另存为之后再用文本编辑器打开去编辑。

1. 准备模板

模板 数据 = 模型

1、将准备好的Word模板文件另存为.xml文件(PS:建议使用WPS来创建Word文件,不建议用Office)

java 模板文件生成word文件(Java根据Freemarker模板生成Word文件)(1)

java 模板文件生成word文件(Java根据Freemarker模板生成Word文件)(2)

2、将.xml文件重命名为.ftl文件

java 模板文件生成word文件(Java根据Freemarker模板生成Word文件)(3)

3、用文本编辑器打开.ftl文件,将内容复制出来,格式化一下,再覆盖原来的内容

(PS:格式化一下是为了方便查找并设置变量/占位符,当然设置好模板参数变量以后可以再压缩后再写会.ftl文件)

另外,强烈不建议在word文件中去编辑设置模板变量,因为.docx文件在另存为.xml文件后,原先好好的一个变量可能就被拆开了,建议另存为之后再用文本编辑器打开去编辑。

java 模板文件生成word文件(Java根据Freemarker模板生成Word文件)(4)

4、设置模板参数(变量/占位符)

java 模板文件生成word文件(Java根据Freemarker模板生成Word文件)(5)

2. 代码实现

pom.xml

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.3</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>demo920</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo920</name> <description>demo920</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-Freemarker</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-core</artifactId> <version>5.8.7</version> </dependency> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.5.13.3</version> </dependency> <!--<dependency> <groupId>com.aspose</groupId> <artifactId>aspose-words</artifactId> <version>22.9</version> <classifier>jdk17</classifier> </dependency>--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </Configuration> </plugin> </plugins> </build> </project>

写个类测试一下

package com.example.demo920; import com.example.demo920.domain.LoanReceipt; import freemarker.template.Configuration; import freemarker.template.Template; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStreamWriter; import java.math.BigDecimal; import java.nio.file.Path; import java.nio.file.Paths; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.HashMap; import java.util.Locale; import java.util.Map; @SpringBootTest class Demo920ApplicationTests { private DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyyyMMddHHmmss" Locale.CHINA); @Test void contextLoads() { } @Test void testGenerateWord() throws Exception { Configuration configuration = new Configuration(Configuration.VERSION_2_3_31); configuration.setDefaultEncoding("UTF-8"); configuration.setClassForTemplateLoading(this.getClass() "/templates"); Template template = configuration.getTemplate("借条.ftl"); Path path = Paths.get("tmp" "contract"); File fileDir = path.toFile(); if (!fileDir.exists()) { fileDir.mkdirs(); } String filename = "借条" "_" LocalDateTime.now().format(DTF) ".docx"; filename = path.toFile() File.separator filename; BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filename))); // template.process(getDataMap() writer); template.process(getData() writer); writer.flush(); writer.close(); } Map<String Object> getDataMap() { Map<String Object> dataMap = new HashMap<>(); dataMap.put("borrowerName" "李白"); dataMap.put("borrowerIdCard" "421302199001012426"); dataMap.put("lenderName" "杜甫"); dataMap.put("amount" 100); dataMap.put("amountInWords" "壹佰"); dataMap.put("startDate" "2022年8月15日"); dataMap.put("endDate" "2022年11月11日"); dataMap.put("borrowingMonths" 3); dataMap.put("interestRate" "1.23"); dataMap.put("guarantorName" "白居易"); dataMap.put("guarantorIdCard" "421302199203152412"); return dataMap; } LoanReceipt getData() { LoanReceipt receipt = new LoanReceipt(); receipt.setBorrowerName("狄仁杰"); receipt.setBorrowerIdCard("421302198710121234"); receipt.setBorrowingMonths(6); receipt.setLenderName("李元芳"); receipt.setAmount(new BigDecimal("101")); receipt.setAmountInWords("壹佰零壹"); receipt.setInterestRate(new BigDecimal("0.6")); receipt.setStartDate("2022年1月1日"); receipt.setEndDate("2022年6月30日"); receipt.setGuarantorName("武则天"); receipt.setGuarantorIdCard("421302199101014567"); return receipt; } }

最主要的是下面两行

// 加载模板 Template template = configuration.getTemplate("借条.ftl"); // 填充数据 template.process(getData() writer);

数据可以是Map也可以是一个对象

改进一下,将生成文件的操作单独写成一个工具方法

package com.example.demo920.util; import cn.hutool.core.io.IoUtil; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; import java.io.*; public class FreemarkerUtils { /** * 生成Word * @param templateDir 模板所在的目录 * @param templateName 模板文件名称 * @param filename 生成的文件(含路径) * @param dataModel 模板参数数据 */ public static void generateWord(File templateDir String templateName String filename Object dataModel) { BufferedWriter writer = null; Configuration configuration = new Configuration(Configuration.VERSION_2_3_31); configuration.setDefaultEncoding("UTF-8"); try { configuration.setDirectoryForTemplateLoading(templateDir); Template template = configuration.getTemplate(templateName); writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filename))); template.process(dataModel writer); writer.flush(); } catch (IOException e) { throw new RuntimeException(e); } catch (TemplateException e) { throw new RuntimeException(e); } finally { IoUtil.close(writer); } } }

再测试一下

package com.example.demo920; import cn.hutool.core.io.IoUtil; import com.example.demo920.util.FreemarkerUtils; import com.example.demo920.util.PdfUtils; import org.junit.jupiter.api.Test; import org.springframework.util.ResourceUtils; import java.io.*; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.time.LocalDateTime; import java.util.HashMap; import java.util.Map; public class WordTest { /** * 1、从文件服务器下载模板文件 * 2、根据业务类型获取需要填充模板的数据 * 3、模板 数据 再经过处理生成新的文件 * 4、将生成后的文件上传到文件服务器,并返回一个文件ID * 5、业务可以保存这个文件ID或者文件的路径 */ @Test void testGenerateWordV1() throws Exception { Path tempPath = Paths.get("tmp" "contract2"); File path = tempPath.toFile(); if (!path.exists()) { path.mkdirs(); } File tempFile = Files.createTempFile(tempPath "qiantiao" ".docx").toFile(); System.out.println(tempFile.getParent()); System.out.println(tempFile.getName()); FileOutputStream fos = new FileOutputStream(tempFile); File templateFile = ResourceUtils.getFile("classpath:templates/借条.ftl"); FileInputStream fis = new FileInputStream(templateFile); IoUtil.copy(fis fos); String filename = "借条" "_" System.currentTimeMillis() ".docx"; filename = "tmp/contract" File.separator filename; FreemarkerUtils.generateWord(new File(tempFile.getParent()) tempFile.getName() filename getDataMap()); } /** * 获取数据 */ Map<String Object> getDataMap() { Map<String Object> dataMap = new HashMap<>(); dataMap.put("borrowerName" "李白2"); dataMap.put("borrowerIdCard" "421302199001012426"); dataMap.put("lenderName" "杜甫"); dataMap.put("amount" 100); dataMap.put("amountInWords" "壹佰"); dataMap.put("startDate" "2022年8月15日"); dataMap.put("endDate" "2022年11月11日"); dataMap.put("borrowingMonths" 3); dataMap.put("interestRate" "1.23"); dataMap.put("guarantorName" "白居易"); dataMap.put("guarantorIdCard" "421302199203152412"); return dataMap; } @Test void testGenerateWord2() throws Exception { File templateDir = ResourceUtils.getFile(ResourceUtils.CLASSPATH_URL_PREFIX "templates"); String templateName = "借条.ftl"; String destFilename = "借条" System.currentTimeMillis() ".docx"; Map<String Object> data = getDataMap(); FreemarkerUtils.generateWord(templateDir templateName destFilename data); } }

java 模板文件生成word文件(Java根据Freemarker模板生成Word文件)(6)

3. PDF文件加水印

有时候,生成或者从服务器下载的文件是需要加水印的,比如标识这个文件是谁下载的之类的

pdf加水印还是比较方便的,用itext组件可以轻松实现

另外,如果最终需要pdf文件,建议直接生成pdf文件,跳过word转pdf的步骤

package com.example.demo920.util; import cn.hutool.core.io.IoUtil; import com.aspose.words.Document; import com.aspose.words.SaveFormat; import com.itextpdf.text.BaseColor; import com.itextpdf.text.DocumentException; import com.itextpdf.text.Element; import com.itextpdf.text.Image; import com.itextpdf.text.pdf.*; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.time.LocalDateTime; /** * @author chengjiansheng * @date 2022/09/21 */ public class PdfUtils { /** * Word转PDF * https://www.aspose.com/ * 注意:Aspose.Words 这个组件是收费的,如果购买的话生成的PDF会有水印。 * 可以去找相应的破解版本,但是我感觉完全可以跳过Word直接生成PDF。 * 比如,可以通过Freemarker直接生成PDF,或者利用iText通过模板生成PDF * @param src * @param dest */ public static void wordToPdf(String src String dest) { File file = new File(src); if (!file.exists()) { throw new RuntimeException("文件不存在"); } FileInputStream fis = null; try { fis = new FileInputStream(file); Document wpd = new Document(fis); wpd.save(dest SaveFormat.PDF); } catch (Exception e) { throw new RuntimeException(e); } finally { IoUtil.close(fis); } } /** * 加水印 * @param src 源文件 * @param dest 目标文件 * @param text 文字 * @param imagePath 图片地址 */ public static void addWatermark(String src String dest String text String imagePath) { try { // 待加水印的文件 PdfReader reader = new PdfReader(src); // 加完水印的文件 PdfStamper stamper = new PdfStamper(reader new FileOutputStream(dest)); // 字体 BaseFont baseFont = BaseFont.createFont("STSong-Light" "UniGB-UCS2-H" BaseFont.NOT_EMBEDDED); // 透明度 PdfGState gs = new PdfGState(); gs.setFillOpacity(0.4f); // PDF文件总页数 int total = reader.getNumberOfPages() 1; // 循环对每一页都加水印 PdfContentByte content; for (int i = 1; i < total; i ) { // 水印在文本之上 content = stamper.getOverContent(i); content.setGState(gs); if (null != imagePath) { Image image = Image.getInstance(imagePath); // image.setAbsolutePosition(150 150); // image.scaleToFit(300 300); // content.addImage(image); for (int x = 0; x < 700; x = x 300) { for (int y = 0; y < 900; y = y 200) { image.setAbsolutePosition(x 50 y 50); image.scaleToFit(100 100); content.addImage(image); } } } if (null != text) { content.beginText(); content.setColorFill(BaseColor.RED); content.setFontAndSize(baseFont 20); // content.showTextAligned(Element.ALIGN_CENTER text 50 50 45); for (int x = 0; x < 700; x = x 300) { for (int y = 0; y < 900; y = y 200) { //水印内容和水印位置 content.showTextAligned(Element.ALIGN_CENTER "哈哈哈哈哈" x - 20 y 10 30); content.showTextAligned(Element.ALIGN_CENTER LocalDateTime.now().toString() x y 30); } } content.endText(); } } stamper.close(); reader.close(); } catch (IOException e) { throw new RuntimeException(e); } catch (DocumentException e) { throw new RuntimeException(e); } } }

跑一下

@Test void testWatermark() { String src2 = "D:\\借条_2.pdf"; String dest2 = "D:\\借条_3.pdf"; String imagePath = "D:\\1.jpg"; PdfUtils.addWatermark(src2 dest2 "哈哈哈哈哈" imagePath); }

加完水印后效果如图

java 模板文件生成word文件(Java根据Freemarker模板生成Word文件)(7)

最后,示例项目结构如图

java 模板文件生成word文件(Java根据Freemarker模板生成Word文件)(8)

原文链接:https://www.cnblogs.com/cjsblog/p/16715294.html?utm_source=tuicool&utm_medium=referral

猜您喜欢: