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

使用Apache POI和POI-OOXML实现word模板文档自动填充功能

 最近接到一个新的需求,用户创建好模板文件保存到模板库,然后使用在线文档编辑器打开模板时,将系统数据填充到模板文件并生成新的word文件,然后在线编辑,研究使用Apache POI和POI-OOXML实现了这个功能。

Maven依赖

        <!-- Apache POI 和 POI-OOXML --><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>5.2.2</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.2</version></dependency>

自动填充的接口

import org.apache.poi.xwpf.usermodel.*;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;@RestController
@RequestMapping("/fill")
public class WordFillController {@PostMapping("/wordFill")public ResponseEntity<?> wordFill() {String templatePath = "E:\\word\\template.docx";String outputPath = "E:\\word\\output.docx";// 待填充进模板的数据Map<String, String> data = new HashMap<>();data.put("name", "张三");data.put("sex", "男");data.put("age", "18");Map<String, String> data1 = new HashMap<>();data1.put("name", "张三1");data1.put("sex", "男1");data1.put("age", "20");Map<String, String> data2 = new HashMap<>();data2.put("name", "李四");data2.put("sex", "男");data2.put("age", "21");Map<String, String> data3 = new HashMap<>();data3.put("name", "王五");data3.put("sex", "女");data3.put("age", "45");List<Map<String, String>> dataList = Arrays.asList(data1, data2, data3);try (// 从模板文件创建word文档对象XWPFDocument doc = new XWPFDocument(Files.newInputStream(Paths.get(templatePath)));// 文件输出流FileOutputStream fos = new FileOutputStream(outputPath)) {replacePlaceholders(doc, data);// 替换占位符fillTable(doc, dataList);// 填充表格// 将文档写入输出流doc.write(fos);// 刷新输出流fos.flush();return ResponseEntity.ok().build();} catch (IOException e) {e.printStackTrace();return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());}}private void replacePlaceholders(XWPFDocument doc, Map<String, String> data) {// 遍历文档中的段落,替换占位符doc.getParagraphs().forEach(paragraph -> {// 遍历段落中的文本,替换占位符paragraph.getRuns().forEach(run -> {// 获取文本内容String text = run.getText(0);// 判断文本是否包含占位符,如果包含,则替换占位符if (text != null && text.contains("${")) {for (Map.Entry<String, String> entry : data.entrySet()) {text = text.replace("${" + entry.getKey() + "}", entry.getValue());}// 设置替换后的文本run.setText(text, 0);}});});}private void fillTable(XWPFDocument doc, List<Map<String, String>> dataList) {XWPFTable table = doc.getTables().get(0); // 获取第一个表格// 获取表格的模板行(假设表格的第一行是标题行,第二行为模板行)XWPFTableRow templateRow = table.getRow(1);// 添加新的行,并删除模板行for (Map<String, String> data : dataList) {XWPFTableRow newRow = table.createRow();// 手动创建每个单元格,并复制模板行的样式for (int i = 0; i < templateRow.getTableCells().size(); i++) {XWPFTableCell templateCell = templateRow.getCell(i);XWPFTableCell newCell = newRow.getCell(i);if (newCell == null) {newCell = newRow.createCell();}// 复制模板行单元格的样式,不复制内容copyCellStyleWithoutText(templateCell, newCell);// 填充数据switch (i) {case 0:newCell.setText(data.get("name"));break;case 1:newCell.setText(data.get("sex"));break;case 2:newCell.setText(data.get("age"));break;}}}// 删除模板行table.removeRow(1);}private void copyCellStyleWithoutText(XWPFTableCell sourceCell, XWPFTableCell targetCell) {// 复制单元格的样式,但不复制文本内容targetCell.getParagraphs().forEach(paragraph -> {XWPFParagraph sourceParagraph = sourceCell.getParagraphs().get(0);paragraph.setAlignment(sourceParagraph.getAlignment());paragraph.setVerticalAlignment(sourceParagraph.getVerticalAlignment());if (!sourceParagraph.getRuns().isEmpty()) {XWPFRun sourceRun = sourceParagraph.getRuns().get(0);XWPFRun targetRun = paragraph.createRun();targetRun.setBold(sourceRun.isBold());targetRun.setItalic(sourceRun.isItalic());targetRun.setFontFamily(sourceRun.getFontFamily());targetRun.setFontSize(sourceRun.getFontSize());}});// 复制单元格背景色等样式targetCell.setColor(sourceCell.getColor());targetCell.setVerticalAlignment(sourceCell.getVerticalAlignment());}
}

word模板

调用接口后生成的新文件

相关文章:

使用Apache POI和POI-OOXML实现word模板文档自动填充功能

最近接到一个新的需求&#xff0c;用户创建好模板文件保存到模板库&#xff0c;然后使用在线文档编辑器打开模板时&#xff0c;将系统数据填充到模板文件并生成新的word文件&#xff0c;然后在线编辑&#xff0c;研究使用Apache POI和POI-OOXML实现了这个功能。 Maven依赖 <…...

【HarmonyOS NEXT星河版开发学习】综合测试案例-各平台评论部分

目录 前言 功能展示 整体页面布局 最新和最热 写评论 点赞功能 界面构建 初始数据的准备 列表项部分的渲染 底部区域 index部分 知识点概述 List组件 List组件简介 ListItem组件详解 ListItemGroup组件介绍 ForEach循环渲染 列表分割线设置 列表排列方向设…...

垂直行业数字化表现抢眼 亚信科技全年利润展望乐观

大数据产业创新服务媒体 ——聚焦数据 改变商业 2024年8月14日&#xff0c;亚信科技控股有限公司&#xff08;股票代码&#xff1a;01675.HK&#xff09;公布了公司截至2024年6月30日的中期业绩。 财报数据显示&#xff0c;2024年上半年&#xff0c;亚信科技的营业收入为人民币…...

EmguCV学习笔记 VB.Net 4.1 颜色变换

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 教程VB.net版本请访问&#xff1a;EmguCV学习笔记 VB.Net 目录-CSDN博客 教程C#版本请访问&#xff1a;EmguCV学习笔记 C# 目录-CSD…...

【MySQL进阶之路】表结构的操作

目录 创建表 查看表 查看数据库有哪些表 查看表结构 查看表的详细信息 修改表 表的重命名 添加一列 修改某一列的属性 删除某一列 对列进行重命名 删除表 个人主页&#xff1a;东洛的克莱斯韦克-CSDN博客 【MySQL进阶之路】MySQL基础——从零认识MySQL-CSDN博客 创…...

3分钟搞定PDF转PPT!你一定要知道的3款转换神器!

在数字办公成为主流的当下&#xff0c;我们每天会收到各类基于数字化方式存储的办公文档&#xff0c;如PDF、PPT、Word、Excel文档等。 日常处理这些文档时&#xff0c;经常需要在不同格式的文档之间进行切换和转换&#xff0c;其中将PDF转换为PPT就是一个非常高频的需求&…...

【EasyExcel】导出excel-设置动态表头并导出数据

需求背景&#xff1a; 导出excel的设置某些表头动态导出(可以根据筛选条件或一些属性的数据量)&#xff0c;方便导出后用户查看想看的信息。 一、技术选型&#xff1a; easyExcel的原生数据处理 二、方案设计&#xff1a; 根据EasyExcel支持的表头List<List<String>…...

深入探索 Elasticsearch 8:新特性与核心原理剖析(上)

深入探索 Elasticsearch 8&#xff1a;新特性与核心原理剖析 目录 一、引言 &#xff08;二&#xff09;版本 8 的重要意义 二、Elasticsearch 8 的新特性 三、Elasticsearch 的核心原理 一、引言 &#xff08;一&#xff09;Elasticsearch 简介 在大数据处理和搜索领域…...

瑜伽馆预约小程序,在线预约,提高商业价值

随着大众生活质量的提高&#xff0c;对休闲运动的关注逐渐加大&#xff0c;瑜伽作为一种身心放松、改善体态的运动&#xff0c;深受女性用户的喜爱。目前&#xff0c;各大瑜伽馆开始结合数字化&#xff0c;建立了新型的线上小程序&#xff0c;帮助大众快速预约体验瑜伽&#xf…...

Python--数据类型转换

在Python中&#xff0c;数据类型的转换是一个常见的操作&#xff0c;涉及将一种数据类型转换为另一种数据类型。Python提供了多种内置函数用于执行这种转换&#xff0c;如 int()、str()、float()、list()、tuple()、set()、dict() 等。下面详细讨论Python的基本数据类型及它们之…...

域控ntdsutil修改架构、域命名、PDC、RID、结构主机

#笔记记录# FSMO盒修改 1、提示访问特权不够&#xff0c;不能执行该操作&#xff0c;0x2098 清除缓存账号密码并修改新架构管理员账号密码即可。 背景&#xff1a;更替架构主机、域命名主机 C:\Windows\system32>ntdsutil ntdsutil: roles fsmo maintenance: ?? …...

解决 Swift 6 全局变量不能满足并发安全(concurrency-safe)读写的问题

概述 WWDC 24 终于在 Swift 十岁生日发布了全新的 Swift 6。这不仅意味着 Swift 进入了全新的“大”版本时代&#xff0c;而且 Swift 编译器终于做到了并发代码执行的“绝对安全”。 不过&#xff0c;从 Swift 5 一步迈入“新时代”的小伙伴们可能对新的并发检查有些许“水土不…...

迈入退休生活,全职开发ue独立游戏上架steam

决定退休了。算了算睡后收入&#xff0c;也可以达到每月一万一&#xff0c;正好可以养家糊口。 既然退休了&#xff0c;那就做些想做的事情&#xff0c;别人养花养草&#xff0c;而我打算开发独立游戏上架steam。 一&#xff0c;盘点下目前的技术体系。 1&#xff0c;图形学底…...

什么是光伏气象站——仁科测控

【仁科测控&#xff0c;品质保障】光伏气象站&#xff0c;‌这一专门为光伏发电系统设计的监测设备&#xff0c;‌其核心能力在于精确且实时地捕捉那些对光伏发电效率产生关键影响的气象因素。‌这些数据不仅为评估光伏电站的发电性能提供了重要依据&#xff0c;‌更是优化运维…...

webshell免杀--免杀入门

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文主要整理webshell免杀的一些基础思路 入门级&#xff0c;不是很深入&#xff0c;主要是整理相关概念 免杀对象 1.各类杀毒软件 类似360&#xff0c;火绒等&#xff0c;查杀己方webshell的软件。 2.各类流量…...

Linux---02---系统目录及文件基本操作命令

课程回顾 操作系统 虚拟机安装 本章重点 Linux系统目录结构 常用命令 熟练区分Linux下各层目录的作用 熟练掌握Linux的常用命令&#xff08;文件命令、时间命令等&#xff09; 一、Linux系统目录结构 1.1 目录结构 /&#xff1a; 根目录&#xff0c;一般根目录下只存放…...

CSP-J/S第一轮初赛模拟赛试题

本模拟试题为本人自创&#xff0c;由于发布在 LG 所以就直接放入链接。 非经允许&#xff0c;不得转载。 本套模拟题只供大家练习使用&#xff0c;不保证难度与真实 CSP-J/S 完全符合。 本模拟赛为专业CSP类型的模拟赛&#xff0c;不存在错题、超出知识的题目。 CSP-J/S 20…...

LangGPT结构化提示词

LangGPT是Language For GPT-like LLMs的简称&#xff0c;中文名为结构化提示词&#xff0c;LangGPT是一个帮助你编写高质量提示词的工具&#xff0c;理论基础是我们提出的一套模块化、标准化的提斯提编写方法论——结构化提示词。我们希望揭开提示工程的神秘面纱&#xff0c;为…...

如何为个人网站更换ssl证书

关键步骤 1&#xff0c;确认服务器类型并下载对应证书&#xff08;这个超级简单&#xff0c;阿里云现在可以下3月免费的&#xff09;&#xff1b; 2&#xff0c;本文以nginx服务为例&#xff0c;主打的就是一个简单且快速让你搞清楚实操流程&#xff1b; linux命令 ps-ef|gr…...

RabbitMQ-消息队列延迟队列一

1、安装rabbitmq 怎么安装rabbitmq请查看之前课程&#xff0c;如果已经安装&#xff0c;请略过此步。 2、创建vendor文件夹或是直接采用PHP框架 mkdir vendor 3、进入文件 cd vendor 4、安装php扩展 composer require php-amqplib/php-amqplib 5、进入上级创建dead文件…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...

Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换

目录 关键点 技术实现1 技术实现2 摘要&#xff1a; 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式&#xff08;自动驾驶、人工驾驶、远程驾驶、主动安全&#xff09;&#xff0c;并通过实时消息推送更新车…...