POI操作Docx的踩坑指南(一)

Java的POI库是Apache软件基金会的一个开源项目,全称为Apache POI(Poor Obfuscation Implementation)。提供了Java操作Microsoft Office格式文件(如Word、Excel、PowerPoint等)的功能。

基本概念

Docx文档主要由文档(doc)、表格(table)、段落(paragraph)、运行(run)组成。

POI中表达对象表格:

中文描述 表达 POI对象
文档 doc XWPFDocument
表格 table XWPFTable
单元格 cell XWPFTableCell
段落 paragraph XWPFParagraph
段落中的一部分 run XWPFRun

XWPFDocument文档的常用方法

List<XWPFParagraph> getParagraphs():获取文档中所有的段落,注意表格中的段落不会包含在内。

List<XWPFTable> getTables():获取文档中所有的表格。

XWPFParagraph createParagraph():创建一个段落到文档最后。

XWPFParagraph insertNewParagraph(XmlCursor):插入一个段落到指定光标之前。

void write(OutputStream):将文档写入到一个输出流中。

XWPFParagraph段落的常用方法

XWPFRun createRun():在段落中创建一个新运行。

List<XWPFRun> getRuns():获取段落中所有的运行,获取到的运行列表是不可修改的。

String getText():获取段落的文本内容,包括所有运行的文本。

void setIndentationFirstLine(int indentation):设置段落的首行缩进。

void setAlignment(ParagraphAlignment align):设置段落的对齐方式。

void setSpacingBetween(double spacing):设置段落的多倍行距,注意固定值和多倍行距的设置有区别。

XWPFRun运行的常用方法

String text():获取运行的文本内容。

void setText(String value, int pos):设置运行的文本内容,pos是可选参数,如果要设置成空字符串,那pos则必须有。

void setFontSize(double size):设置字体大小。

常用操作

将某一个run替换为空字符串

java 复制代码
run.setText("",0);

复制段落字体大小

java 复制代码
int fontSize = oldParagraph.getRuns().get(0).getFontSize();
if (fontSize == -1 && oldParagraph.getStyle() != null) {
    // 从run中没有获取到字体大小
    XWPFStyle style = oldParagraph.getDocument().getStyles().getStyle(oldParagraph.getStyle());
    if (style != null && style.getCTStyle().isSetRPr()) {
        CTHpsMeasure sz = style.getCTStyle().getRPr().getSz();
        fontSize = sz.getVal().intValue() / 2;
    }
}
if(fontSize != -1){
    newParagraph.getRuns().get(0).setFontSize(fontSize);
}

复制段落行高以及段前后间距

java 复制代码
// 获取旧段落的CTPPr来操作行高
CTSpacing oldSpacing = oldParagraph.getCTP().getPPr().getSpacing();

if (oldSpacing != null) {
    CTSpacing newSpacing = newParagraph.getCTP().getPPr().isSetSpacing() ?
            newParagraph.getCTP().getPPr().getSpacing() :
               newParagraph.getCTP().getPPr().addNewSpacing();

    // 如果旧段落有固定行高设置,将其复制到新段落
    if (oldSpacing.isSetLine()) {
        newSpacing.setLine(oldSpacing.getLine());
        newSpacing.setLineRule(oldSpacing.getLineRule()); // 确保行高规则也复制
    }

    // 复制间距前后设置
    if (oldSpacing.isSetBefore()) {
        newSpacing.setBefore(oldSpacing.getBefore());
    }
    if (oldSpacing.isSetAfter()) {
        newSpacing.setAfter(oldSpacing.getAfter());
    }
}else{
    newParagraph.setSpacingBetween(oldParagraph.getSpacingBetween());
}

字体、文本颜色等需要根据自己需求添加进去。

相关推荐
码路飞3 小时前
GPT-5.3 Instant 终于学会好好说话了,顺手对比了下同天发布的 Gemini 3.1 Flash-Lite
java·javascript
SimonKing4 小时前
OpenCode AI编程助手如何添加Skills,优化项目!
java·后端·程序员
Seven975 小时前
剑指offer-80、⼆叉树中和为某⼀值的路径(二)
java
怒放吧德德17 小时前
Netty 4.2 入门指南:从概念到第一个程序
java·后端·netty
雨中飘荡的记忆18 小时前
大流量下库存扣减的数据库瓶颈:Redis分片缓存解决方案
java·redis·后端
心之语歌21 小时前
基于注解+拦截器的API动态路由实现方案
java·后端
华仔啊1 天前
Stream 代码越写越难看?JDFrame 让 Java 逻辑回归优雅
java·后端
ray_liang1 天前
用六边形架构与整洁架构对比是伪命题?
java·架构
Ray Liang1 天前
用六边形架构与整洁架构对比是伪命题?
java·python·c#·架构设计
Java水解1 天前
Java 中间件:Dubbo 服务降级(Mock 机制)
java·后端