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

springBoot使用XWPFDocument 和 LoopRowTableRenderPolicy 两种方式填充数据到word模版中

依赖

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.3</version></dependency><dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-base</artifactId><version>4.4.0</version></dependency><dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-word</artifactId><version>4.4.0</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>
</dependencies>

controller

package com.ruoyi.web.controller.materials;import com.ruoyi.materials.domain.wordVo.ReportData;
import com.ruoyi.materials.domain.wordVo.Student;
import com.ruoyi.materials.service.WordExportService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;/*** Created with IntelliJ IDEA.** @Author: yxy* @Date: 2025/07/09/14:22* @Description:*/
@RestController
@RequestMapping("/api/word")
public class WordExportController {@Autowiredprivate WordExportService wordExportService;@GetMapping("/xwpf")public ResponseEntity<InputStreamResource> exportByXWPFDocument() throws Exception {ReportData data = createSampleData();InputStream is = wordExportService.generateWordByXWPFDocument(data);return buildResponseEntity(is, "xwpf_export.docx");}@GetMapping("/looprow")public ResponseEntity<InputStreamResource> exportByLoopRowTable() throws Exception {ReportData data = createSampleData();InputStream is = wordExportService.generateWordByLoopRowTable(data);return buildResponseEntity(is, "looprow_export.docx");}private ReportData createSampleData() {ReportData data = new ReportData();data.setTitle("学生信息报告");data.setDate("2025年7月10日");data.setSchoolName("示例中学");List<Student> students = new ArrayList<>();Student student = new Student();student.setName("张三");student.setAge(18);Student student2 = new Student();student2.setName("李四");student2.setAge(19);students.add(student);students.add(student2);data.setStudents(students);return data;}private ResponseEntity<InputStreamResource> buildResponseEntity(InputStream is, String fileName) throws Exception {HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_OCTET_STREAM).body(new InputStreamResource(is));}}

ServiceImpl

package com.ruoyi.materials.service.impl;import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.ruoyi.materials.domain.wordVo.ReportData;
import com.ruoyi.materials.domain.wordVo.Student;
import com.ruoyi.materials.service.WordExportService;
import org.apache.poi.xwpf.usermodel.*;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** Created with IntelliJ IDEA.** @Author: yxy* @Date: 2025/07/09/14:27* @Description:*/
@Service
public class WordExportServiceImpl implements WordExportService {public InputStream generateWordByXWPFDocument(ReportData data) throws IOException {// 加载模板ClassPathResource resource = new ClassPathResource("templates/xwpf_template.docx");try (InputStream is = resource.getInputStream();XWPFDocument document = new XWPFDocument(is);ByteArrayOutputStream out = new ByteArrayOutputStream()) {// 替换文本内容replaceText(document, "${title}", data.getTitle());replaceText(document, "${date}", data.getDate());replaceText(document, "${schoolName}", data.getSchoolName());// 填充表格数据fillTable(document, data.getStudents());document.write(out);return new ByteArrayInputStream(out.toByteArray());}}private void replaceText(XWPFDocument document, String placeholder, String replacement) {for (XWPFParagraph p : document.getParagraphs()) {for (XWPFRun r : p.getRuns()) {String text = r.getText(0);if (text != null && text.contains(placeholder)) {text = text.replace(placeholder, replacement);r.setText(text, 0);}}}}private void fillTable(XWPFDocument document, List<Student> students) {// 假设第一个表格是学生列表if (document.getTables().size() > 0) {XWPFTable table = document.getTables().get(0);// 从第二行开始插入数据(第一行是表头)for (int i = 0; i < students.size(); i++) {Student student = students.get(i);XWPFTableRow row;// 如果行数不够,创建新行if (i + 1 >= table.getNumberOfRows()) {row = table.createRow();} else {row = table.getRow(i + 1);}// 填充单元格数据setCellText(row, 0, student.getName());setCellText(row, 1, student.getAge().toString());setCellText(row, 2, student.getGender());setCellText(row, 3, student.getAddress());}}}private void setCellText(XWPFTableRow row, int cellIndex, String text) {XWPFTableCell cell = row.getCell(cellIndex);if (cell == null) {cell = row.addNewTableCell();}cell.setText(text);}@Overridepublic InputStream generateWordByLoopRowTable(ReportData data) throws Exception {Map<String, Object> rm = new HashMap<>();rm.put("title",data.getTitle());rm.put("date",data.getDate());rm.put("schoolName",data.getSchoolName());rm.put("table", data.getStudents());//使用行循环插件LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();//绑定插件所属名为listConfigure config = Configure.builder().bind("table", policy).build();// 调用 exportFile 方法生成文件并返回return exportFile(rm, config);}public InputStream exportFile(Map<String, Object> map, Configure config) throws IOException {// 获取模板文件的输入流try (InputStream ins = getClass().getResourceAsStream("/templates/looprow_template.docx")) {if (ins == null) {throw new FileNotFoundException("模板文件未找到");}// 编译模板并渲染数据XWPFTemplate template = XWPFTemplate.compile(ins, config).render(map);// 生成字节输出流ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();template.write(byteArrayOutputStream);// 返回 ByteArrayInputStream 用于后续处理return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());}}}

实体类

import lombok.Data;
import java.util.List;@Data
public class ReportData {private String title;private String date;private String schoolName;private List<Student> students;
}import com.ruoyi.common.annotation.Excel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@AllArgsConstructor
@NoArgsConstructor
@Data
public class Student {@Excel(name = "name")private String name;@Excel(name = "age")private Integer age;@Excel(name = "gender")private String gender;@Excel(name = "address")private String address;private byte[] photo;
}

模版
xwpf_template.docx
在这里插入图片描述
looprow_template.docx
在这里插入图片描述

http://www.lryc.cn/news/583132.html

相关文章:

  • Android-重学kotlin(协程源码第一阶段)新学习总结
  • npm init vue@latestnpm error code ETIMEDOUT
  • 网络请求与现实生活:用办理业务类比理解HTTP通信
  • kotlin学习,val使用get()的问题
  • AI 知识库 2.0 时代!2025 设备管理系统如何实现 “智慧运维”?
  • Docker完全指南:从入门到生产环境实战
  • 将.net应用部署到Linux服务器
  • 深入解析 .NET 泛型:从原理到实战优化
  • Docker 搭建 Harbor 私有仓库
  • 使用 Docker 搭建 Go Web 应用开发环境——AI教你学Docker
  • mac m1安装大模型工具vllm
  • Vue的watch和React的useEffect
  • “AI 曼哈顿计划”:科技竞赛还是人类挑战?
  • 电商销量第一,贝锐向日葵智能远控硬件背后的软硬结合战略
  • Mac mini 高性价比扩容 + Crossover 游戏实测 全流程手册
  • Python-FAQ-单例模式
  • 深入理解图像二值化:从静态图像到视频流实时处理
  • 一天两道力扣(3)
  • 计蒜客T3473丑数、Leetcode2401最长优雅子数组、Leetcode167两数之和、Leetcode581最短无序连续子数组
  • 开源链动2+1模式与AI智能名片融合下的S2B2C商城小程序源码:重构大零售时代新生态
  • 【工具】Pycharm隐藏文件类型或目录
  • Hive MetaStore的实现和优化
  • AI+智慧园区 | 事件处置自动化——大模型重构园区治理逻辑
  • 向量空间 线性代数
  • 两张图片对比clip功能
  • 在 PyCharm 中安装并配置 Node.js 的指南
  • 整合Spring、Spring MVC与MyBatis:构建高效Java Web应用
  • Linux的 `test`命令(或等价中括号写法 `[空格expression空格]`)的用法详解. 笔记250709
  • 自制明信片DIY:让心意更有温度
  • python Gui界面小白入门学习