使用Apache POI操作Word文档:从入门到实战

Apache POI是Java生态中最流行的Microsoft Office文档操作库之一,它为Word文档(包括传统的.doc格式和现代的.docx格式)提供了全面的API支持。本文将详细介绍如何使用Apache POI创建、读取和修改Word文档。

一、Apache POI简介与环境准备

1. Apache POI组件

Apache POI包含多个组件用于处理不同Office文档:

  • POI-HWPF:处理.doc格式(Word 97-2003)
  • POI-XWPF:处理.docx格式(Word 2007及以后版本)
  • POI-HSLF:处理PowerPoint
  • POI-HSSF/XSSF:处理Excel

2. 添加Maven依赖

<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>5.2.3</version>
</dependency>
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.3</version>
</dependency>

3. 核心类介绍

  • XWPFDocument:代表整个Word文档
  • XWPFParagraph:文档中的段落
  • XWPFRun:段落中的文本运行(具有相同格式的文本段)
  • XWPFTable:表格
  • XWPFPicture:图片

二、创建Word文档

1. 创建简单文档

import org.apache.poi.xwpf.usermodel.*;import java.io.FileOutputStream;
import java.io.IOException;public class SimpleDocumentCreator {public static void main(String[] args) throws IOException {// 1. 创建空文档XWPFDocument document = new XWPFDocument();// 2. 创建段落XWPFParagraph title = document.createParagraph();title.setAlignment(ParagraphAlignment.CENTER);// 3. 创建文本运行并设置样式XWPFRun titleRun = title.createRun();titleRun.setText("Apache POI示例文档");titleRun.setBold(true);titleRun.setFontSize(16);// 4. 添加正文段落XWPFParagraph body = document.createParagraph();body.setAlignment(ParagraphAlignment.LEFT);body.setIndentationFirstLine(600); // 首行缩进XWPFRun bodyRun = body.createRun();bodyRun.setText("这是使用Apache POI创建的Word文档。");bodyRun.addBreak(); // 换行bodyRun.setText("POI支持丰富的文本格式设置。");// 5. 保存文档try (FileOutputStream out = new FileOutputStream("SimpleDocument.docx")) {document.write(out);}document.close();System.out.println("文档创建成功!");}
}

2. 添加复杂格式

// 创建带格式的段落
XWPFParagraph styledPara = document.createParagraph();
styledPara.setAlignment(ParagraphAlignment.BOTH); // 两端对齐XWPFRun styledRun = styledPara.createRun();
styledRun.setText("格式丰富的文本:");
styledRun.setColor("FF0000"); // 红色
styledRun.setFontFamily("宋体");
styledRun.addBreak();// 添加不同格式的文本
styledRun = styledPara.createRun();
styledRun.setText("粗体+斜体");
styledRun.setBold(true);
styledRun.setItalic(true);
styledRun.addTab(); // 制表符styledRun = styledPara.createRun();
styledRun.setText("下划线");
styledRun.setUnderline(UnderlinePatterns.SINGLE);

三、操作表格

1. 创建表格

// 创建3行4列的表格
XWPFTable table = document.createTable(3, 4);// 设置表格宽度
table.setWidth("100%");// 填充表头
XWPFTableRow headerRow = table.getRow(0);
headerRow.getCell(0).setText("序号");
headerRow.getCell(1).setText("姓名");
headerRow.getCell(2).setText("年龄");
headerRow.getCell(3).setText("部门");// 填充数据
for (int i = 1; i < 3; i++) {XWPFTableRow row = table.getRow(i);row.getCell(0).setText(String.valueOf(i));row.getCell(1).setText("员工" + i);row.getCell(2).setText(String.valueOf(20 + i));row.getCell(3).setText(i % 2 == 0 ? "技术部" : "市场部");
}// 合并单元格
table.getRow(2).getCell(3).setText("备注:所有部门");
table.addNewColSpan(2, 3, 2); // 合并第3行的第3-4列

2. 表格样式设置

// 设置表格边框
CTTblPr tblPr = table.getCTTbl().getTblPr();
CTBorder border = tblPr.addNewTblBorders();
border.addNewBottom().setVal(STBorder.SINGLE);
border.addNewTop().setVal(STBorder.SINGLE);
border.addNewLeft().setVal(STBorder.SINGLE);
border.addNewRight().setVal(STBorder.SINGLE);
border.addNewInsideH().setVal(STBorder.SINGLE);
border.addNewInsideV().setVal(STBorder.SINGLE);// 设置表头背景色
for (XWPFTableCell cell : headerRow.getTableCells()) {cell.setColor("D3D3D3"); // 浅灰色背景
}

四、插入图片

import org.apache.poi.util.Units;// 从文件插入图片
try (FileInputStream is = new FileInputStream("logo.png")) {XWPFParagraph imagePara = document.createParagraph();imagePara.setAlignment(ParagraphAlignment.CENTER);XWPFRun imageRun = imagePara.createRun();imageRun.addPicture(is, Document.PICTURE_TYPE_PNG, "logo.png", Units.toEMU(200), // 宽度Units.toEMU(100)); // 高度
}// 从字节数组插入图片
byte[] imageData = getImageData(); // 获取图片字节数组的方法
XWPFRun imageRun = document.createParagraph().createRun();
imageRun.addPicture(new ByteArrayInputStream(imageData),Document.PICTURE_TYPE_JPEG,"photo.jpg",Units.toEMU(150),Units.toEMU(150));

五、读取和修改现有文档

1. 读取文档内容

public void readDocument(String filePath) throws IOException {try (FileInputStream fis = new FileInputStream(filePath);XWPFDocument document = new XWPFDocument(fis)) {System.out.println("==== 段落 ====");for (XWPFParagraph para : document.getParagraphs()) {System.out.println(para.getText());}System.out.println("\n==== 表格 ====");for (XWPFTable table : document.getTables()) {for (XWPFTableRow row : table.getRows()) {for (XWPFTableCell cell : row.getTableCells()) {System.out.print(cell.getText() + "\t");}System.out.println();}}}
}

2. 修改现有文档

public void modifyDocument(String inputPath, String outputPath) throws IOException {try (FileInputStream fis = new FileInputStream(inputPath);XWPFDocument document = new XWPFDocument(fis)) {// 修改第一个段落XWPFParagraph firstPara = document.getParagraphs().get(0);if (firstPara != null) {XWPFRun run = firstPara.createRun();run.setText("\n(本文件由系统自动生成)");run.setItalic(true);run.setColor("808080");}// 在文档末尾添加新内容XWPFParagraph newPara = document.createParagraph();newPara.setAlignment(ParagraphAlignment.RIGHT);XWPFRun newRun = newPara.createRun();newRun.setText("生成时间: " + LocalDate.now());newRun.addBreak(BreakType.PAGE); // 分页符// 保存修改后的文档try (FileOutputStream fos = new FileOutputStream(outputPath)) {document.write(fos);}}
}

六、高级功能

1. 页眉页脚设置

// 创建页眉
XWPFHeader header = document.createHeader(HeaderFooterType.DEFAULT);
XWPFParagraph headerPara = header.createParagraph();
headerPara.setAlignment(ParagraphAlignment.RIGHT);
XWPFRun headerRun = headerPara.createRun();
headerRun.setText("公司机密");
headerRun.setColor("FF0000");// 创建页脚
XWPFFooter footer = document.createFooter(HeaderFooterType.DEFAULT);
XWPFParagraph footerPara = footer.createParagraph();
footerPara.setAlignment(ParagraphAlignment.CENTER);
XWPFRun footerRun = footerPara.createRun();
footerRun.setText("页码: ");
footerRun.getCTR().addNewFldSimple().setInstr("PAGE \\* MERGEFORMAT");

2. 目录生成

// 创建目录段落
XWPFParagraph tocPara = document.createParagraph();
tocPara.setStyle("TOCHeading");XWPFRun tocRun = tocPara.createRun();
tocRun.setText("目录");
tocRun.setBold(true);
tocRun.setFontSize(16);
tocRun.addBreak();// 添加目录字段
tocRun = tocPara.createRun();
tocRun.getCTR().addNewFldSimple().setInstr("TOC \\o \"1-3\" \\h \\z \\u");

3. 批注(注释)添加

// 在第一个段落添加批注
XWPFParagraph firstPara = document.getParagraphs().get(0);
String commentText = "这是系统自动添加的批注";
String commentAuthor = "AutoSystem";
CTComment ctComment = document.getDocument().getBody().addNewComment();
ctComment.setAuthor(commentAuthor);
ctComment.setDate(new GregorianCalendar());
ctComment.addNewP().addNewR().addNewT().setStringValue(commentText);// 将段落与批注关联
CTMarkupRange range = firstPara.getCTP().addNewCommentRangeStart();
range.setId(ctComment.getId());
firstPara.getCTP().addNewCommentRangeEnd().setId(ctComment.getId());
firstPara.getCTP().addNewR().addNewCommentReference().setId(ctComment.getId());

七、性能优化与最佳实践

1. 大文件处理优化

对于大文档,建议使用事件模型(XWPFEventAPI)而非DOM模型:

import org.apache.poi.xwpf.eventusermodel.*;public class LargeDocumentReader {public static void main(String[] args) throws Exception {OPCPackage pkg = OPCPackage.open("large.docx");XWPFEventBasedParser parser = new XWPFEventBasedParser();parser.parse(pkg, new XWPFVisitor() {@Overridepublic void visitParagraph(XWPFParagraph paragraph) {System.out.println("段落: " + paragraph.getText());}@Overridepublic void visitTable(XWPFTable table) {System.out.println("发现表格");}});pkg.close();}
}

2. 内存管理

  • 及时关闭文档对象和流
  • 对于批量处理,考虑复用XWPFDocument对象
  • 使用try-with-resources确保资源释放

3. 样式重用

// 创建并重用样式
CTSectPr sectPr = document.getDocument().getBody().addNewSectPr();
CTPageSz pageSz = sectPr.addNewPgSz();
pageSz.setW(BigInteger.valueOf(12240)); // A4宽度
pageSz.setH(BigInteger.valueOf(15840)); // A4高度// 创建段落样式
CTStyle ctStyle = CTStyle.Factory.newInstance();
ctStyle.setStyleId("MyStyle");
CTPPr pPr = ctStyle.addNewPPr();
pPr.addNewSpacing().setAfter(BigInteger.valueOf(200)); // 段后间距
document.getStyle().addStyle(ctStyle);// 应用样式
XWPFParagraph para = document.createParagraph();
para.setStyle("MyStyle");

八、常见问题与解决方案

1. 中文乱码问题

确保使用支持中文的字体:

run.setFontFamily("宋体");

或者在文档级别设置默认字体:

document.getStyles().setDefaultFonts("宋体", null);

2. 格式不兼容问题

  • 尽量使用.docx格式而非.doc格式
  • 避免使用太新的Office特性
  • 在生成文档后进行兼容性测试

3. 性能问题

  • 对于大文档,分批次处理内容
  • 避免频繁创建/销毁XWPFRun对象
  • 考虑缓存常用样式

九、总结

Apache POI提供了强大而灵活的API来操作Word文档,从简单的文本生成到复杂的格式设置、表格处理和图片插入都能胜任。通过本文的介绍,您应该已经掌握了:

  1. 基本的文档创建与保存
  2. 文本格式设置与段落控制
  3. 表格的创建与样式设置
  4. 图片插入方法
  5. 现有文档的读取与修改
  6. 高级功能如页眉页脚、目录生成
  7. 性能优化技巧

在实际项目中,建议根据具体需求选择合适的API,并注意资源管理和性能优化。对于更复杂的需求,可以结合模板引擎或考虑商业解决方案。

Apache POI的官方文档和社区资源丰富,遇到问题时可以查阅:

  • 官方文档:https://poi.apache.org/
  • API文档:https://poi.apache.org/apidocs/index.html
  • 示例代码:https://svn.apache.org/repos/asf/poi/trunk/src/examples/src/org/apache/poi/examples/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/pingmian/84796.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CentOS 7.3环境中部署Kerberos集群

CentOS 7.3环境中部署Kerberos集群 文章目录 CentOS 7.3环境中部署Kerberos集群环境安装服务包 Kerberos MS 规划安装 KDC Master Server配置文件/etc/krb5.conf/var/kerberos/krb5kdc/kdc.conf/var/kerberos/krb5kdc/kadm5.acl 创建Kerberos数据库启动与停止服务创建管理员创建…

1 Studying《Arm A715 Software Optimization Guide》

目录 1 Introduction 1.1 Product revision status 1.2 Intended audience 1.3 Scope 1.4 Conventions 1.5 Useful resources 2 Overview 2.1 Pipeline overview 3 Instruction characteristics 3.1 Instruction tables 3.2 Legend for reading the utilized pipeli…

第二十四章 24.QoS(CCNA)

第二十四章 24.QoS(CCNA) 介绍了switch QoS的配置方法 注释&#xff1a; 学习资源是B站的CCNA by Sean_Ning CCNA 最新CCNA 200-301 视频教程(含免费实验环境&#xff09; PS&#xff1a;喜欢的可以去买下他的课程&#xff0c;不贵&#xff0c;讲的很细 To be continued……

什么是稳定币?

稳定币&#xff08;Stablecoin&#xff09;是一种特殊的加密货币&#xff0c;其核心目标是维持价格稳定&#xff0c;通常与某种稳定资产&#xff08;如美元、黄金等&#xff09;挂钩。 一、为什么需要稳定币&#xff1f; 普通加密货币&#xff08;如比特币、以太坊&#xff09…

伺服学习(IS620N)

DI 端子的基本概念 DI 端子是伺服驱动器上的数字输入接口&#xff0c;用于接收外部开关、按钮或PLC的24V/0V信号。每个端子的功能可通过参数灵活配置&#xff08;如启停、限位等&#xff09;。 核心要点 功能设置&#xff1a;通过驱动器参数组&#xff08;如H03&#xff09;…

基于Python的气象数据分析及可视化研究

目录 一.&#x1f981;前言二.&#x1f981;开源代码与组件使用情况说明三.&#x1f981;核心功能1. ✅算法设计2. ✅PyEcharts库3. ✅Flask框架4. ✅爬虫5. ✅部署项目 四.&#x1f981;演示效果1. 管理员模块1.1 用户管理 2. 用户模块2.1 登录系统2.2 查看实时数据2.3 查看天…

Excel处理控件Aspose.Cells教程:使用 C# 在 Excel 中应用数据验证

Excel 中的数据验证可确保用户在工作表中仅输入有效数据。在设计表单、收集数据或构建财务模型时&#xff0c;数据验证有助于维护结构并最大限度地减少用户错误。在本文中&#xff0c;我们将向您展示如何使用 C# 以编程方式在 Excel 中应用数据验证。 Aspose.Cells 最新版下载…

AI应用:计算机视觉相关技术总结

计算机视觉概述 计算机视觉&#xff08;Computer Vision, CV&#xff09;是一门让计算机从图像或视频中 “理解” 和 “解释” 视觉信息的技术&#xff0c;涉及多学科交叉&#xff08;如数学、统计学、机器学习、信号处理等&#xff09;。以下从技术体系、核心任务、关键技术、…

人口贩卖暑期威胁消解:算法协同提升安全预警

随着暑期的到来&#xff0c;人员流动加剧&#xff0c;人口贩卖等恶性犯罪活动进入高发阶段&#xff0c;景区、车站、商场等公共场所成为潜在风险区域。传统安防手段在应对此类隐蔽性强、危害性大的犯罪时显得力不从心。为此&#xff0c;引入基于视觉分析的多维度算法技术&#…

【DSP笔记 · 第3章】数字世界的“棱镜”:离散傅里叶变换(DFT)完全解析

数字世界的“棱镜”&#xff1a;离散傅里叶变换&#xff08;DFT&#xff09;完全解析 在上一章&#xff0c;我们探索了Z变换和离散时间傅里叶变换&#xff08;DTFT&#xff09;。我们知道&#xff0c;DTFT是一个无比强大的理论工具&#xff0c;它能将一个时域离散序列的“基因…

卷积神经网络的参数量及尺度变化计算

文章目录 前言1.卷积2.参数量的计算2.1案例一2.2案例二 3.奇怪的优化思想3.1使用小核卷积替换大核卷积3.2卷积核11的应用 4.输出图像尺寸的计算4.1Same convolution4.2具体计算规则4.3转置卷积 小结 前言 本篇博客主要介绍卷积基本概念&#xff0c;卷积神经网络的参数量计算、…

OpenCV——图像平滑

图像平滑 一、图像的噪声1.1、噪声来源1.2、噪声类型1.3、噪声模拟 二、滤波器三、线性滤波3.1、均值滤波3.2、方框滤波3.3、高斯滤波 四、非线性滤波4.1、中值滤波4.2、双边滤波 图像在采集和传输过程中容易受到各种因素的影响而产生噪声&#xff0c;而噪声会对图像的正确解读…

鸿蒙系统备份恢复

鸿蒙系统尝试者&#xff0c;在纯血鸿蒙与鸿蒙4.2/4.3之前反复横跳&#xff0c;中间折腾… 目录 鸿蒙4.2/4.3升级鸿蒙5.0系统备份 鸿蒙5.0回退鸿蒙4.2/4.3系统备份备份恢复 华为手机助手注意 鸿蒙4.2/4.3升级鸿蒙5.0 系统备份 云空间备份手机本地备份华为手机助手备份 鸿蒙5.…

JS进阶 Day03

1.两种面向编程思想 2.构造函数实现封装以及存在的问题 下面就引出了原型对象 3.原型对象prototype 共享原理图&#xff1a; 4.数组扩展案例-求最大值和数组求和 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><…

visual studio小番茄插件某些快捷键失效

问题 AltO 切换头文件和源文件失效。 背景 最近升级了 visual studio&#xff0c;多了一些插件 原因 Alt O 快捷键被其他插件占用了 解决方案 工具 → 选项 → 环境 → 键盘 搜索这个 VAssistX.OpenCorrespondingFile&#xff08;切换头/源文件&#xff09; 发现命令的快…

基于单片机的PT100温度变送器设计

基于单片机的PT100温度变送器设计 文章目录 基于单片机的PT100温度变送器设计前言一、资源分享二、系统框架三、硬件准备1.主控制器2、PT100温度传感器3、显示屏4、WIFI模块5、USB转RS485模块6、SP3485EN7、K11-11D3 四、设计PCB1、安装下载立创EDA专业版2、画原理图3、摆放元器…

Git 清理指南:如何从版本库中移除误提交的文件(保留本地文件)

场景 在 Git 项目中&#xff0c;我们可能会不小心提交了本应忽略的文件&#xff08;如 node_modules/、.env、*.log 等&#xff09;&#xff0c;导致仓库体积膨胀或敏感信息泄露。本文介绍如何从 Git 历史中彻底删除这些文件&#xff0c;同时保留本地文件。 解决方案 1. 确认…

服务器数据恢复—重装系统导致XFS文件系统分区无法访问的数据恢复案例

服务器数据恢复环境&故障&#xff1a; 一台服务器上通过磁盘柜RAID卡组建的riad5磁盘阵列&#xff0c;服务器上层安装Linux操作系统&#xff0c;搭建XFS文件系统。服务器上层分配一个LUN&#xff0c;并划分了两个分区。通过LVM扩容的方式将sdc1分区加入到了root_lv中&#…

在QtCreator中使用GitHubCopilot

文章目录 1.github copilot账号2. 安装node.js3.安装 GitHub Copilot Neovim plugin4.在Qt中启用4.1.在extension中启用4.2.在配置中启用4.3.使用/禁用 5.评价 在最新版的QtCreator中&#xff0c;已经通过Extension集成了GitHubCopilot进来。 我用的是16.0.2版本的&#xff08;…

岛屿周长问题的三种解法:直接计数法、数学计算法与深度优先搜索

问题描述 给定一个二维网格 grid&#xff0c;其中1表示陆地&#xff0c;0表示水域。网格中的格子水平和垂直方向相连&#xff08;对角线不相连&#xff09;。网格中恰好有一个岛屿&#xff08;即一个或多个相连的陆地格子&#xff09;&#xff0c;需要计算这个岛屿的周长。 解…