使用Apache POI为Word文档添加文字水印
XWPFDocument是Apache POI库中的核心类,用于操作Microsoft Word (.docx)文档,特别是在处理XML形式的Open XML格式文档时使用。XWPFDocument是Apache POI中用于处理Word文档(.docx)的主要类,它代表一个完整的Word文档,提供了一系列方法来创建、读取、修改和保存Word文档内容。
一、主要功能
1、文档创建与加载
new XWPFDocument()
:创建一个新的空白Word文档- 从文件加载:
XWPFDocument document = new XWPFDocument(new FileInputStream("document.docx"));
2、文档内容操作
getParagraphs()
:获取文档中的所有段落createParagraph()
:创建新的段落createRun()
:在段落中创建文本运行addTable(int rows, int cols)
:添加表格replaceText(String searchStr, String replaceStr)
:替换文档中的文本deleteParagraph(int index)
:删除指定索引位置的段落
3、文档保存
write(OutputStream out)
:将文档内容写入输出流
二、使用示例
1、创建并保存Word文档
// 创建新的XWPFDocument
XWPFDocument document = new XWPFDocument();
// 添加段落
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
run.setText("Hello, World!");
run.setFontSize(12);
// 保存文档
FileOutputStream out = new FileOutputStream("example.docx");
document.write(out);
out.close();
document.close();
2、设置页眉和页脚
// 获取页眉页脚策略
XWPFHeaderFooterPolicy headerFooterPolicy = document.getHeaderFooterPolicy();
if (headerFooterPolicy == null) {
headerFooterPolicy = document.createHeaderFooterPolicy();
}
// 创建页眉
XWPFHeader header = headerFooterPolicy.createHeader(HeaderFooterType.DEFAULT);
header.createParagraph().createRun().setText("页眉内容");
// 创建页脚
XWPFFooter footer = headerFooterPolicy.createFooter(HeaderFooterType.DEFAULT);
footer.createParagraph().createRun().setText("页脚内容");
三、核心组件
XWPFDocument中主要包含以下几种对象:
- XWPFParagraph:代表一个段落
- XWPFRun:代表具有相同属性的一段文本
- XWPFTable:代表一个表格
- XWPFTableRow:表格的一行
- XWPFTableCell:表格对应的一个单元格
四、常见用法
- 读取Word文档内容
- 编辑Word文档内容
- 生成Word文档
- 添加水印(如知识库中提到的,通过页脚添加文字水印)
- 替换模板中的占位符
五、与NPOI的关系
在C#中,NPOI是Apache POI的.NET版本,提供类似的XWPFDocument类,用于操作Word文档。C#中使用XWPFDocument的语法与Java类似,只是命名空间和类名有所不同。
六、注意事项
- Apache POI对Word文档的处理是基于XML的,因此某些高级格式可能不被完全支持
- 文档操作时需要处理好资源释放,避免内存泄漏
- 对于复杂文档,可能需要组合使用多个XWPF类
XWPFDocument是处理Word文档的强有力工具,特别适合于自动化生成和处理Word文档的场景。
七、使用Apache POI为Word文档添加文字水印
package com.nn3n.service.export.utils;
import com.microsoft.schemas.office.office.CTLock;
import com.microsoft.schemas.vml.*;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.wp.usermodel.HeaderFooterType;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFHeader;
import org.openxmlformats.schemas.officeDocument.x2006.sharedTypes.STTrueFalse;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import java.io.*;
public class WatermarkWordUtil {
private static final String FONT_NAME = "宋体";
private static final String FONT_SIZE = "50pt";
private static final String FONT_COLOR = "#808080";
/**
* 一个字平均长度,单位pt,用于:计算文本占用的长度(文本总个数*单字长度)
*/
private static final Integer WIDTH_PER_WORD = 80;
/**
* 与顶部的间距
*/
private static Integer STYLE_TOP = 10;
/**
* 文本旋转角度
*/
private static final String STYLE_ROTATION = "-45";
public static void waterMarkDocXDocument(String filepath, String outputPath, String fingerText) {
try (
OutputStream out = new FileOutputStream(outputPath);
InputStream in = new FileInputStream(filepath);
OPCPackage srcPackage = OPCPackage.open(in);
XWPFDocument doc = new XWPFDocument(srcPackage)
) {
STYLE_TOP = 300;
waterMarkDocXDocument(doc, fingerText);
STYLE_TOP = 700;
waterMarkDocXDocument(doc, fingerText);
// 输出新文档
doc.write(out);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static void waterMarkDocXDocument(XWPFDocument doc, String fingerText) {
// 如果之前已经创建过 DEFAULT 的Header,将会复用
XWPFHeader header = doc.createHeader(HeaderFooterType.DEFAULT);
int size = header.getParagraphs().size();
if (size == 0) {
header.createParagraph();
}
CTP ctp = header.getParagraphArray(0).getCTP();
byte[] rsidr = doc.getDocument().getBody().getPArray(0).getRsidR();
byte[] rsidrDefault = doc.getDocument().getBody().getPArray(0).getRsidRDefault();
ctp.setRsidP(rsidr);
ctp.setRsidRDefault(rsidrDefault);
CTPPr ppr = ctp.addNewPPr();
ppr.addNewPStyle().setVal("Header");
// 开始加水印
CTR ctr = ctp.addNewR();
CTRPr ctrpr = ctr.addNewRPr();
ctrpr.addNewNoProof();
CTGroup group = CTGroup.Factory.newInstance();
CTShapetype shapeType = group.addNewShapetype();
CTTextPath shapeTypeTextPath = shapeType.addNewTextpath();
shapeTypeTextPath.setOn(STTrueFalse.T);
shapeTypeTextPath.setFitshape(STTrueFalse.T);
CTLock lock = shapeType.addNewLock();
lock.setExt(STExt.VIEW);
CTShape shape = group.addNewShape();
shape.setId("PowerPlusWaterMarkObject");
shape.setSpid("_x0000_s102");
shape.setType("#_x0000_t136");
// 设置形状样式(旋转,位置,相对路径等参数)
shape.setStyle(getShapeStyle(fingerText));
shape.setFillcolor(FONT_COLOR);
// 字体设置为实心
shape.setStroked(STTrueFalse.FALSE);
// 绘制文本的路径
CTTextPath shapeTextPath = shape.addNewTextpath();
// 设置文本字体与大小
shapeTextPath.setStyle("font-family:" + FONT_NAME + ";font-size:" + FONT_SIZE);
shapeTextPath.setString(fingerText);
CTPicture pict = ctr.addNewPict();
pict.set(group);
}
/**
* 构建Shape的样式参数
*
* @param fingerText
* @return
*/
private static String getShapeStyle(String fingerText) {
StringBuilder sb = new StringBuilder();
// 文本path绘制的定位方式
sb.append("position: ").append("absolute");
// 计算文本占用的长度(文本总个数*单字长度)
sb.append(";width: ").append(fingerText.length() * WIDTH_PER_WORD).append("pt");
// 字体高度
sb.append(";height: ").append("50pt");
sb.append(";z-index: ").append("-251654144");
sb.append(";mso-wrap-edited: ").append("f");
// 设置水印的间隔,这是一个大坑,不能用top,必须要margin-top。
sb.append(";margin-top: ").append(STYLE_TOP);
sb.append(";mso-position-horizontal-relative: ").append("page");
sb.append(";mso-position-vertical-relative: ").append("page");
sb.append(";mso-position-vertical: ").append("left");
sb.append(";mso-position-horizontal: ").append("center");
sb.append(";rotation: ").append(STYLE_ROTATION);
return sb.toString();
}
}
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 软件从业者Hort
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果