当前位置: 首页 > news >正文

java填充word模版导出word文件支持导出pdf,支持本地下载和网络下载,使用jar包

可参考poi-tl文档:http://deepoove.com/poi-tl/

pom依赖

<!-- word导出 --><dependency><groupId>com.deepoove</groupId><artifactId>poi-tl</artifactId><version>1.7.3</version></dependency><!--  上面需要的依赖--><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.2</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-schemas</artifactId><version>4.1.2</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version></dependency><!--word 2 pdf start--><dependency><groupId>com.documents4j</groupId><artifactId>documents4j-local</artifactId><version>1.0.3</version></dependency><dependency><groupId>com.documents4j</groupId><artifactId>documents4j-transformer-msoffice-word</artifactId><version>1.0.3</version></dependency>

制作模版

文本标签:使用{{属性名}}做处理
在这里插入图片描述
列表集合:列表中集合使用{{集合名}},列表属性用[属性名]处理
在这里插入图片描述

在这里插入图片描述
图片列表:集合处理方式都一样{{集合名}},图片属性增加@[@属性名]
在这里插入图片描述

业务代码

package org.springblade.modules.api.controller;import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.PictureRenderData;
import com.deepoove.poi.policy.HackLoopTableRenderPolicy;
import io.swagger.annotations.ApiOperation;
import org.springblade.core.tool.api.R;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;/*** word模版填充导出*/
@RestController
public class TestExportWord {/*** 生成填充后的Word模板*/private static XWPFTemplate generateWordTemplate() throws Exception {// 使用resource模版:放在resource的templates里/*ClassPathResource templateResource = new ClassPathResource("templates/农安简报模板测试表格.docx");HackLoopTableRenderPolicy policy = new HackLoopTableRenderPolicy();//创建策略Configure config = Configure.newBuilder().bind("list", policy).bind("imgList", policy).build();XWPFTemplate template = XWPFTemplate.compile(templateResource.getInputStream(), config);template.render(newData());return template;*/// 本地测试用String filePath = "F:\\machine\\naReport\\测试使用填充导出word.docx";//测试环境用InputStream inputStream = new FileInputStream(filePath);HackLoopTableRenderPolicy policy = new HackLoopTableRenderPolicy();Configure config = Configure.newBuilder().bind("list", policy).bind("imgList", policy).build();XWPFTemplate template = XWPFTemplate.compile(inputStream, config);template.render(newData());return template;}/*** 填充数据源* 其中data存放的key值与模板中的文本域值相对应*/public static Map<String, Object> newData() {Map<String, Object> data = new HashMap<String, Object>();//key要与模板中的别名一一对应data.put("date", LocalDateTime.now());data.put("msg", "锄禾日当午");List<Map<String, Object>> list = new ArrayList<>();Map<String, Object> map;int num = 1;while (num < 3) {map = new HashMap<>();map.put("name", "张三" + num);map.put("birthday", "2025-01-01");map.put("age", num);map.put("class", "高三" + num + "班");list.add(map);num++;}data.put("list", list);List<Map<String, Object>> maps1 = new ArrayList<>();for (int i = 1; i <= 2; i++) {Map<String, Object> m = new HashMap<>();if (i % 2 == 0) {// 读取本地磁盘图片m.put("url", new PictureRenderData(50, 50, "D:\\壁纸\\火影.jpg"));} else {// 读取本地磁盘图片m.put("url", new PictureRenderData(30, 30, "D:\\壁纸\\海贼王.jpg"));}m.put("text", "共" + 2 + "张图片,当前为第" + (i) + "张");maps1.add(m);}data.put("imgList", maps1);return data;}/*** 数据处理,下载盗到本地** @param args*/public static void main(String[] args) {try {// 使用封装的方法生成模板XWPFTemplate template = generateWordTemplate();// 4.设置响应头,导出文件名String fileName = System.currentTimeMillis() + "test.docx";String fileNamePdf = System.currentTimeMillis() + "test.pdf";//则保存到本地文件夹// 创建 SimpleDateFormat 对象,指定格式为 "yyyyMMdd"SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");// 获取当前日期Date now = new Date();// 格式化日期String formattedDate = sdf.format(now);String localWord = saveToLocal(template, fileName, "D:\\");//转换为pdfExportWordToPdfUtil.wordToPdf(localWord, "D:\\" + fileNamePdf);} catch (Exception e) {System.out.println("导出异常" + e.getMessage());}}/*** 保存到本地文件夹** @param template 模板对象* @param fileName 文件名* @param path     本地路径(可选)*/public static String saveToLocal(XWPFTemplate template, String fileName, String path) throws Exception {// 如果未指定本地路径,使用默认路径if (path == null || path.isEmpty()) {// 获取用户主目录String userHome = System.getProperty("user.home");// 创建默认下载目录File downloadDir = new File(userHome, "Downloads");if (!downloadDir.exists()) {downloadDir.mkdirs();}path = downloadDir.getAbsolutePath();}// 确保路径存在File dir = new File(path);if (!dir.exists()) {dir.mkdirs();}// 创建文件File outputFile = new File(dir, fileName);try (FileOutputStream out = new FileOutputStream(outputFile)) {template.write(out);System.out.println("文件已保存到本地: " + outputFile.getAbsolutePath());} finally {template.close();}return outputFile.getAbsolutePath();}/*** 网络下载** @param response HttpServletResponse* @param template 模板对象* @param fileName 文件名*/public static void downloadToNetwork(HttpServletResponse response, XWPFTemplate template, String fileName) throws Exception {// 设置响应头String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");  // 将 "+" 替换为 "%20"String contentDisposition = String.format("attachment; filename=\"%s\"; filename*=UTF-8''%s",encodedFileName, encodedFileName);response.setHeader("Content-Disposition", contentDisposition);response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");// 写入响应流try (OutputStream out = response.getOutputStream()) {template.write(out);out.flush();} finally {template.close();}}/*** 生成报告*/@GetMapping("/generateReport")public void generateReport(HttpServletResponse response) throws Exception {// 使用封装的方法生成模板XWPFTemplate template = generateWordTemplate();// 设置文件名String fileName = "测试网略下载_" + new SimpleDateFormat("yyyyMMdd").format(new Date()) + ".docx";// 下载到网络downloadToNetwork(response, template, fileName);}
}

word转pdf工具类

package org.springblade.modules.api.utils;import com.documents4j.api.DocumentType;
import com.documents4j.api.IConverter;
import com.documents4j.job.LocalConverter;
import org.springblade.core.tool.utils.Func;import java.io.*;public class ExportWordToPdfUtil {/*** Word转PDF** @param filePath    源docx文件目录及名称  示例:F:\\machine\\naReport\\20251022\\1761112860572运行情况简报.docx* @param outFilePath 输出文件目录及名称 示例:F:\\machine\\naReport\\20251022\\1761112860572运行情况简报.pdf*/public static void wordToPdf(String filePath, String outFilePath) {//NaReport naReport = new NaReport();File inputWord = new File(filePath);File outputFile = new File(outFilePath);// 确保输出目录存在File parentDir = outputFile.getParentFile();if (parentDir != null && !parentDir.exists()) {parentDir.mkdirs();}// 如果输出文件已存在则删除(实现替换)if (outputFile.exists()) {if (!outputFile.delete()) {System.err.println("警告:无法删除已存在的文件,可能被占用或无权限: " + outFilePath);}}IConverter converter = null;try (InputStream doc = new FileInputStream(inputWord);OutputStream outputStream = new FileOutputStream(outputFile)) {converter = LocalConverter.builder().build();boolean flag = converter.convert(doc).as(DocumentType.DOCX)  // 修正为DOCX(原代码误用DOC).to(outputStream).as(DocumentType.PDF).execute();if (flag) {// 获取文件大小和绝对路径long fileSize = outputFile.length();System.out.println("文件大小:" + smartConvert(fileSize));System.out.println("文件名:" + outFilePath + " 转换成功!");// TODO返回格式:文件大小|绝对路径,我这里是为了自己处理,不需要的可以直接删除//return naReport;} else {System.err.println("转换失败,未知错误");}} catch (Exception e) {// 转换失败时删除可能生成的不完整文件if (outputFile.exists()) {outputFile.delete();}e.printStackTrace();} finally {// 确保无论成功与否都关闭转换器if (converter != null) {converter.shutDown();}}}/*** 将字节大小转换为易读的字符串(自动选择最佳单位)** @param bytes 文件大小(字节)* @return 格式化后的字符串(如:1.23 MB)*/public static String formatFileSize(long bytes) {if (bytes < 1024) {return bytes + " B";}double size = bytes;String[] units = {"KB", "MB", "GB", "TB"};int unitIndex = -1;while (size >= 1024 && unitIndex < units.length - 1) {size /= 1024;unitIndex++;}return String.format("%.2f %s", size, units[unitIndex]);}/*** 转换为KB(保留两位小数)** @param bytes 文件大小(字节)* @return KB大小的字符串表示*/public static String toKB(long bytes) {double kb = bytes / 1024.0;return String.format("%.2f KB", kb);}/*** 转换为MB(保留两位小数)** @param bytes 文件大小(字节)* @return MB大小的字符串表示*/public static String toMB(long bytes) {double mb = bytes / (1024.0 * 1024.0);return String.format("%.2f MB", mb);}/*** 智能转换(自动选择KB或MB)** @param bytes 文件大小(字节)* @return 最合适的单位表示*/public static String smartConvert(long bytes) {if (bytes < 1024 * 1024) { // 小于1MBreturn toKB(bytes);} else {return toMB(bytes);}}public static void main(String[] args) {String filePath = "F:\\machine\\naReport\\20251022\\1761112860572运行情况简报.docx";String outFilePath = "F:/machine/naReport/20251022/1761112860572运行情况简报.pdf";wordToPdf(filePath, outFilePath);}
}

最终结果

在这里插入图片描述
在这里插入图片描述

http://www.dtcms.com/a/520421.html

相关文章:

  • 网络安全:Apache Druid 安全漏洞
  • 宁波公司建站模板wordpress用户调用
  • 70%的RAG性能与分块有关
  • 足球网站开发外贸网站优化推广
  • Uncertainty-Aware Null Space Networks for Data-Consistent Image Reconstruction
  • 孝感网站seodw做网站的导航栏怎么做
  • LeetCode 每日一题 166. 分数到小数
  • 封面论文丨薄膜铌酸锂平台实现强耦合电光调制,《Light Sci. Appl. 》报道机器学习优化新范式
  • 做外贸找产品上哪个网站好flash素材网站有哪些
  • Rust内存安全:所有权与生命周期的精妙设计
  • 2510rs,稳定裸函数
  • 西安住房建设局网站首页企业网站 设计需求
  • LangChain:让大模型具备思考与行动能力的框架
  • MySQL 及 SQL 注入详细说明
  • 医院移动护理系统源码,JAVA移动护理系统源码,医院移动护士站源码
  • 网站建设营销型新型塑料建筑模板图片
  • Linux 有哪些功能相似的命令
  • 外贸推广网站冲压加工瑞安有做网站吗
  • 【开题答辩实录分享】以《租房小程序的设计和实现》为例进行答辩实录分享
  • vscode debug Transformer源码说明
  • 仓颉语言核心特性深度解析:类型系统与内存安全实践
  • IP 地址 (Internet Protocol Address) 详细介绍
  • PHP网站开发常用函数房城乡建设部网站
  • 开源的SSR框架都是怎么实现的?
  • RLVR训练多模态文档解析模型-olmOCR 2技术方案(模型、数据和代码均开源)
  • AI 领域热门方向或代表性技术/模型
  • MySQL 体系结构、SQL 执行与设计范式
  • 个人网站如何搭建国家企业信用信息网官网
  • MySQL学习之SQL语法与操作
  • “麻烦您了”英语怎么说?