You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用Apache POI添加Word文字水印:createWatermark未显示斜灰文本

解决Apache POI createWatermark 水印样式不生效的问题

我之前也踩过这个坑!createWatermark 方法看似省心,但在不同POI版本、不同Word文档格式(.doc vs .docx)下经常会出现斜体灰色样式不显示的情况,甚至连水印本身都可能失踪。下面是几个我亲测有效的解决思路:

1. 先排查版本和文档格式兼容性

  • 如果你用的是POI 3.x版本,对.docx格式的水印支持非常有限,createWatermark 生成的样式几乎都会失效,建议直接升级到POI 4.x及以上版本(目前稳定版是5.x)。
  • 如果你处理的是旧版.doc格式(HWPF),createWatermark 的行为本来就不稳定,别纠结默认方法,直接看下面的手动实现方案。

2. 手动构建自定义样式的水印(最可靠)

默认的createWatermark 会硬编码一些样式,但很多时候没正确应用到文档里。不如手动创建页眉段落,精细控制字体样式和位置:

import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

// 假设你已经创建了XWPFDocument实例
XWPFDocument doc = new XWPFDocument();

// 获取或创建页眉页脚策略
XWPFHeaderFooterPolicy headerFooterPolicy = doc.getHeaderFooterPolicy();
if (headerFooterPolicy == null) {
    headerFooterPolicy = doc.createHeaderFooterPolicy();
}
XWPFHeader header = headerFooterPolicy.getHeader(XWPFHeaderFooterPolicy.DEFAULT);

// 创建水印专用段落
XWPFParagraph watermarkPara = header.createParagraph();
watermarkPara.setAlignment(ParagraphAlignment.CENTER); // 水平居中

// 设置段落垂直居中(让水印在页眉区域居中显示)
CTP ctp = watermarkPara.getCTP();
CTPPr ppr = ctp.getPPr() != null ? ctp.getPPr() : ctp.addNewPPr();
CTVerticalJc verticalJc = ppr.addNewVerticalJc();
verticalJc.setVal(STVerticalJc.CENTER);

// 创建文本运行并设置样式
XWPFRun run = watermarkPara.createRun();
run.setText("Watermark");
run.setItalic(true); // 斜体
run.setColor("808080"); // 灰色(RGB值)
run.setFontSize(48); // 大字号更像水印
run.setTextPosition(180); // 调整垂直位置,避免和页眉内容重叠

// 可选:添加文字旋转效果(模拟传统水印的倾斜)
CTText ctText = run.getCTR().getTArray(0);
CTRPr rPr = run.getCTR().getRPr() != null ? run.getCTR().getRPr() : run.getCTR().addNewRPr();
CTTextEffect textEffect = rPr.addNewTextEffect();
textEffect.setRot("15"); // 旋转15度,可根据需要调整

这个方法能完全掌控水印的样式,几乎不会出现样式丢失的问题。

3. 针对.doc格式的特殊处理

如果是处理旧版.doc(HWPF)文档,需要用形状来实现水印:

import org.apache.poi.hwpf.usermodel.*;
import org.apache.poi.hwpf.usermodel.ShapeTypes;

HWPFDocument doc = new HWPFDocument();
HeaderStories headerStories = doc.getHeaderStories();
Range headerRange = headerStories.getHeader();

// 创建文本框形状作为水印容器
Shape watermarkShape = new Shape(doc, ShapeTypes.TEXT_BOX);
watermarkShape.setHorizontalPosition(250); // 水平位置
watermarkShape.setVerticalPosition(200); // 垂直位置
watermarkShape.setWidth(500);
watermarkShape.setHeight(150);
watermarkShape.setRotation(30); // 倾斜30度

// 向形状中添加水印文本
Paragraph shapePara = watermarkShape.addNewParagraph();
CharacterRun cr = shapePara.addNewCharacterRun();
cr.setText("Watermark");
cr.setItalic(true);
cr.setColor("808080");
cr.setFontSize(24);

// 将形状插入页眉
headerRange.insertAfter(watermarkShape);

4. 验证文档的打开方式

有时候水印在WPS中显示正常,但在Microsoft Word里异常,反之亦然。建议用Microsoft Word打开生成的文档进行验证,因为POI是针对Word格式标准开发的,第三方软件的解析可能存在差异。

如果还是不行,检查一下你的Maven/Gradle依赖,确保poipoi-ooxml的版本一致,避免依赖冲突导致的奇怪问题。

内容的提问来源于stack exchange,提问作者user2223296

火山引擎 最新活动