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中主要包含以下几种对象:

  1. XWPFParagraph:代表一个段落
  2. XWPFRun:代表具有相同属性的一段文本
  3. XWPFTable:代表一个表格
  4. XWPFTableRow:表格的一行
  5. 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();
    }
}

wechat_2025-10-09_144713_146.png