You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache POI实现HTML转Word时@page CSS样式失效的解决方案咨询

解决Apache POI HTML转Word中@page CSS样式不生效的问题

首先得明确:你当前使用的POIFSFileSystem生成的是旧版的二进制.doc格式,这种方式本质是把HTML作为Word的嵌入式片段处理,但Word的旧格式对CSS的支持极其有限——@page这类页面级的CSS规则完全不在支持范围内,所以你的页码样式根本不会被识别。

下面给你两种可行的解决方向,优先推荐第一种:


方案1:切换到XWPF生成.docx文档(推荐,支持更完善)

Apache POI的XWPF组件是专门处理.docx格式的,对HTML转Word的支持更好,而且可以通过API直接控制页面布局和页码(替代@page的效果)。

步骤1:添加必要依赖(Maven示例)

确保你的项目引入了POI的OOXML相关依赖:

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

步骤2:修改转换代码

我们先把HTML转成XWPFDocument,再手动实现@page里的页码和边距需求:

import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.xwpf.converter.xhtml.XHTMLConverter;
import org.apache.poi.xwpf.converter.xhtml.XHTMLOptions;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.*;
import java.math.BigInteger;

public void convertHtmlToDocx(String html, OutputStream outputStream) throws Exception {
    // 解析HTML为W3C文档对象
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = factory.newDocumentBuilder();
    Document w3cDoc = builder.parse(new InputSource(new StringReader(html)));

    // 将HTML转换为XWPFDocument
    XWPFDocument xwpfDoc = new XWPFDocument();
    XHTMLOptions options = XHTMLOptions.create();
    XHTMLConverter.getInstance().convert(w3cDoc, xwpfDoc, options);

    // 实现@bottom-right的页码效果
    XWPFHeaderFooterPolicy headerFooterPolicy = xwpfDoc.getHeaderFooterPolicy();
    if (headerFooterPolicy == null) {
        headerFooterPolicy = xwpfDoc.createHeaderFooterPolicy();
    }
    // 创建默认页脚
    XWPFFooter footer = headerFooterPolicy.createFooter(XWPFHeaderFooterPolicy.DEFAULT);
    XWPFParagraph footerPara = footer.createParagraph();
    footerPara.setAlignment(ParagraphAlignment.RIGHT); // 右对齐对应@bottom-right

    XWPFRun run = footerPara.createRun();
    run.setText("Page ");
    // 插入动态页码字段
    run.getCTR().addNewFldSimple().setInstr("PAGE");

    // 实现@page里的padding-right:20px(Word用缇作为单位,20px≈14缇)
    CTSectPr sectPr = xwpfDoc.getDocument().getBody().addNewSectPr();
    CTPageMar pageMar = sectPr.addNewPgMar();
    // 默认右边距是144缇(1英寸),加上20px对应的14缇
    pageMar.setRight(BigInteger.valueOf(144 + 14));

    // 写入输出流
    xwpfDoc.write(outputStream);
    xwpfDoc.close();
}

说明

这里没有直接依赖CSS的@page,而是用XWPF的API精确控制页脚和页面边距——因为当前版本的XHTMLConverter对@page的支持仍然不完善,但API方式可以保证效果稳定。


方案2:坚持生成.doc格式(不推荐,限制多)

如果必须生成旧版.doc格式,只能用HWPF组件,但HWPF对HTML的支持极差,且页面属性的操作非常繁琐:

关键代码示例

import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.usermodel.*;
import org.apache.poi.hwpf.model.SectionProperties;

import java.io.*;

public void convertHtmlToDoc(String html, OutputStream outputStream) throws Exception {
    HWPFDocument doc = new HWPFDocument();
    Range range = doc.getRange();

    // 注意:HWPF转换HTML的能力很弱,可能需要先把HTML转成纯文本或简单格式再插入
    // 这里省略HTML转HWPF的具体步骤(可尝试用JTidy预处理HTML)

    // 设置页面右边距(增加20px对应的14缇)
    SectionProperties sectProps = range.getSection(0).getSectionProperties();
    sectProps.setRightMargin(sectProps.getRightMargin() + 14);

    // 添加页脚页码(HWPF的字段处理很繁琐,这里是简化示例)
    HeaderStories headerStories = doc.getHeaderStories();
    Range footerRange = headerStories.getFooterRange();
    footerRange.insertAfter("Page ");
    Field pageField = footerRange.insertAfter("");
    pageField.setType(Field.PAGE);
    pageField.update();

    doc.write(outputStream);
    doc.close();
}

注意

这个方案会面临样式丢失、页码位置难以精确控制等问题,除非有硬性要求,否则不建议使用。


总结

优先选择切换到.docx格式的方案,用XWPF的API实现@page里的需求,这是目前最稳定可靠的方式。旧版.doc格式的限制太多,很难完美实现你的页面样式要求。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 03:47:44