【Java处理word文档】

Java处理word文档

  • 前言
  • 一、word是什么?
  • 二、Java处理word
    • 2.1、依赖包
    • 2.2、加载word样式
    • 2.3、读入文件
    • 2.4、单一样式段落
    • 2.5、复合样式段落
    • 2.6、将段落写入word
    • 2.7、word表格
    • 2.8、超链接
    • 2.9、写入样式及文件保存
  • 总结
  • 示例源码
    • 样式xml
    • WordConstant
    • WordStylesUtil
    • WordUtil
    • Main


前言

这篇文章记录Java处理word的相关内容。
看完以下内容,word中的大多数甚至所有操作你都可以通过java代码实现。

注意:此篇文章处理的word格式为Microsoft Office Word 2007及之后的版本,也就是后缀为docx的word文件。


一、word是什么?

word其实是xml文件(格式为Microsoft Office Word 2007及之后的版本)。手动创建一个word文档,将后缀名改为zip,然后使用解压缩工具解压。在解压结果的word目录下有一个document.xml文件。这个文件就是word文档的主要内容。还有一个styles.xml文件,此文件定义word中的样式。

二、Java处理word

首先给一个通过java生成的word文档的示例。
在这里插入图片描述
将word文档后缀修改为zip,然后解压得到如下图中的文件:
在这里插入图片描述
打开word目录后,如下,其中的document.xml就是word文档的主要内容。
在这里插入图片描述
下来我们针对这个例子进行说明。

2.1、依赖包

以下依赖包中包含hutool相关的内容,此依赖包和处理word没有任何关系,只是其中的各种工具类用起来比较方便。

        <dependency><groupId>org.docx4j</groupId><artifactId>docx4j-JAXB-Internal</artifactId><version>8.2.9</version></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.3.10</version></dependency>

2.2、加载word样式

word的样式是存放在一个名为styles.xml的文件中,我们在处理word样式的时候为了方便,可以将想要的样式存放在代码的资源文件中,然后通过docx4j提供的api加载即可。以下为加载样式xml文件的代码。(样式xml文件后续在示例代码中给出源码)

InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream("styles.xml");
Styles styles = (Styles) XmlUtils.unmarshal(resourceAsStream);

2.3、读入文件

通过docx4j依赖包提供的api加载文件(此文件如果不存在则会自动创建),返回WordprocessingMLPackage对象,后续处理都是在其基础上。

File outputFile = new File("C:\\Users\\admin\\Desktop\\test.docx");
// Create the package 建包
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
// 另存为新的文件 保存
// 如果原文件已存在的话,里面的内容会被清空
wordMLPackage.save(docxFile);
WordprocessingMLPackage wPackage = WordprocessingMLPackage.load(outputFile);

2.4、单一样式段落

首先我们看一下word文档解压后的document.xml文件中的内容。
先看示例中的“标题1”。

		<w:p w:rsidR="001272E8" w:rsidRDefault="00EC6803"><w:pPr><w:pStyle w:val="1"/></w:pPr><w:r><w:t>标题</w:t></w:r><w:r><w:t>1</w:t></w:r></w:p>

通过docx4j提供的ObjectFactory factory = Context.getWmlObjectFactory();对象工厂。ObjectFactory可以生成段落、表格、超链接等等与word相关的对象。
以下java代码生成一个单一样式的段落。
通过xml文件我们可以看到,首先我们需要创建一个段落P对象,同时设置段落的ppr。然后还需要创建一个R对象,将R对象通过P.getContent().add(R);与段落进行关联。

    /*** 根据样式ID获取段落对象P** @param paragraphText* @param styleId* @return org.docx4j.wml.P*/public static P getPByStyleId(String paragraphText, String styleId) {Style style = WordStylesUtil.getStyleById(styleId);ObjectFactory factory = Context.getWmlObjectFactory();P paragraph = factory.createP();R run = factory.createR();run.setRPr(style.getRPr());String[] split = paragraphText == null ? new String[0] : paragraphText.split("\n");if (split.length > 1) {List<Child> list = new ArrayList<>();for (String s : split) {Text text = factory.createText();text.setValue(s);// 保留前后空格text.setSpace(SchemaSymbols.ATTVAL_PRESERVE);// 将换行符进行处理为</Br>Br br = factory.createBr();list.add(text);list.add(br);}run.getContent().addAll(list);} else {Text text = factory.createText();text.setValue(paragraphText);run.getContent().add(text);}paragraph.getContent().add(run);paragraph.setPPr(style.getPPr());return paragraph;}

2.5、复合样式段落

示例中的“title:测试title”,其中“title:”进行了加粗处理。
先看word文档解压后的document.xml文件中的内容。

		<w:p w:rsidR="001272E8" w:rsidRDefault="00EC6803"><w:proofErr w:type="spellStart"/><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:b/><w:bCs/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>title</w:t></w:r><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:b/><w:bCs/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t></w:t></w:r><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>测试</w:t></w:r><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>title</w:t></w:r><w:proofErr w:type="spellEnd"/></w:p>

可以看到段落P中存在多个R,每个R都有其自己特定的rPr。
以下java代码实现。

    /*** 给word中写入复合样式的段落信息** @param wPackage* @param context   二维数组,二维中的数据只能有两个元素,第一个为段落内容,第二个为样式ID。例如:[["内容1","样式1"],["内容2","样式2"]]*/public static void complexPWrite(WordprocessingMLPackage wPackage, String[][] context) {if (context.length <= 0) {return;}P complexP = WordUtil.getComplexP();for (int i = 0; i < context.length; i++) {String[] temp = context[i];if (temp.length != 2) {continue;}String paragraph = temp[0];String styleId = temp[1];Style style = WordStylesUtil.getStyleById(styleId);if (StringUtils.isBlank(paragraph) || style == null) {continue;}addRun(complexP, paragraph, style);}// 写入insertOneParagraph(wPackage, complexP);}/*** 复合段落某一段数据处理** @param paragraph         整个段落* @param paragraphText     当前处理的某段数据* @param style             样式* @return void*/public static void addRun(P paragraph, String paragraphText, Style style) {ObjectFactory factory = Context.getWmlObjectFactory();Text text = factory.createText();text.setValue(paragraphText);// 保留前后空格text.setSpace(SchemaSymbols.ATTVAL_PRESERVE);R run = factory.createR();run.getContent().add(text);run.setRPr(style.getRPr());paragraph.getContent().add(run);}

2.6、将段落写入word

    /*** 添加段落,可以是复合样式的段落** @param wPackage* @param paragraph 用户自定义好的段落(包括样式与内容)* @return void*/public static void insertOneParagraph(WordprocessingMLPackage wPackage, P paragraph) {wPackage.getMainDocumentPart().getContent().add(paragraph);}

2.7、word表格

先看word文档解压后的document.xml文件中的表格内容。
以下内容看着很长,其实总结下来就是表格tbl下嵌套行tr,行tr下嵌套单元格tc,单元格tc中示例中给的都是段落P。其他就是表格的样式处理。

		<w:tbl><w:tblPr><w:tblW w:w="0" w:type="auto"/><w:tblBorders><w:top w:val="single" w:sz="4" w:space="0" w:color="auto"/><w:left w:val="single" w:sz="4" w:space="0" w:color="auto"/><w:bottom w:val="single" w:sz="4" w:space="0" w:color="auto"/><w:right w:val="single" w:sz="4" w:space="0" w:color="auto"/><w:insideH w:val="single" w:sz="4" w:space="0" w:color="auto"/><w:insideV w:val="single" w:sz="4" w:space="0" w:color="auto"/></w:tblBorders><w:tblLayout w:type="fixed"/><w:tblLook w:val="04A0" w:firstRow="1" w:lastRow="0" w:firstColumn="1" w:lastColumn="0" w:noHBand="0" w:noVBand="1"/></w:tblPr><w:tblGrid><w:gridCol w:w="2312"/><w:gridCol w:w="1386"/><w:gridCol w:w="1386"/><w:gridCol w:w="4159"/></w:tblGrid><w:tr w:rsidR="001272E8"><w:tc><w:tcPr><w:tcW w:w="25" w:type="pct"/><w:shd w:val="clear" w:color="auto" w:fill="9CC2E5" w:themeFill="accent1" w:themeFillTint="99"/></w:tcPr><w:p w:rsidR="001272E8" w:rsidRDefault="00EC6803"><w:pPr><w:spacing w:before="130" w:after="50"/><w:jc w:val="center"/></w:pPr><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:b/><w:bCs/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>单元格</w:t></w:r><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:b/><w:bCs/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>1</w:t></w:r></w:p></w:tc><w:tc><w:tcPr><w:tcW w:w="15" w:type="pct"/><w:shd w:val="clear" w:color="auto" w:fill="9CC2E5" w:themeFill="accent1" w:themeFillTint="99"/></w:tcPr><w:p w:rsidR="001272E8" w:rsidRDefault="00EC6803"><w:pPr><w:spacing w:before="130" w:after="50"/><w:jc w:val="center"/></w:pPr><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:b/><w:bCs/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>单元格</w:t></w:r><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:b/><w:bCs/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>2</w:t></w:r></w:p></w:tc><w:tc><w:tcPr><w:tcW w:w="15" w:type="pct"/><w:shd w:val="clear" w:color="auto" w:fill="9CC2E5" w:themeFill="accent1" w:themeFillTint="99"/></w:tcPr><w:p w:rsidR="001272E8" w:rsidRDefault="00EC6803"><w:pPr><w:spacing w:before="130" w:after="50"/><w:jc w:val="center"/></w:pPr><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:b/><w:bCs/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>单元格</w:t></w:r><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:b/><w:bCs/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>3</w:t></w:r></w:p></w:tc><w:tc><w:tcPr><w:tcW w:w="45" w:type="pct"/><w:shd w:val="clear" w:color="auto" w:fill="9CC2E5" w:themeFill="accent1" w:themeFillTint="99"/></w:tcPr><w:p w:rsidR="001272E8" w:rsidRDefault="00EC6803"><w:pPr><w:spacing w:before="130" w:after="50"/><w:jc w:val="center"/></w:pPr><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:b/><w:bCs/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>单元格</w:t></w:r><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:b/><w:bCs/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>4</w:t></w:r></w:p></w:tc></w:tr><w:tr w:rsidR="001272E8"><w:tc><w:tcPr><w:tcW w:w="25" w:type="pct"/></w:tcPr><w:p w:rsidR="001272E8" w:rsidRDefault="00EC6803"><w:pPr><w:spacing w:before="130" w:after="50"/></w:pPr><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>单元格</w:t></w:r><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>1</w:t></w:r></w:p></w:tc><w:tc><w:tcPr><w:tcW w:w="15" w:type="pct"/></w:tcPr><w:p w:rsidR="001272E8" w:rsidRDefault="00EC6803"><w:pPr><w:spacing w:before="130" w:after="50"/></w:pPr><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>单元格</w:t></w:r><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>2</w:t></w:r></w:p></w:tc><w:tc><w:tcPr><w:tcW w:w="15" w:type="pct"/></w:tcPr><w:p w:rsidR="001272E8" w:rsidRDefault="00EC6803"><w:pPr><w:spacing w:before="130" w:after="50"/><w:jc w:val="center"/></w:pPr><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t></w:t></w:r></w:p></w:tc><w:tc><w:tcPr><w:tcW w:w="45" w:type="pct"/></w:tcPr><w:p w:rsidR="001272E8" w:rsidRDefault="00EC6803"><w:pPr><w:spacing w:before="130" w:after="50"/></w:pPr><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>单元格</w:t></w:r><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>4</w:t></w:r></w:p></w:tc></w:tr><w:tr w:rsidR="001272E8"><w:tc><w:tcPr><w:tcW w:w="25" w:type="pct"/></w:tcPr><w:p w:rsidR="001272E8" w:rsidRDefault="00EC6803"><w:pPr><w:spacing w:before="130" w:after="50"/></w:pPr><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>单元格</w:t></w:r><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>1</w:t></w:r></w:p></w:tc><w:tc><w:tcPr><w:tcW w:w="15" w:type="pct"/></w:tcPr><w:p w:rsidR="001272E8" w:rsidRDefault="00EC6803"><w:pPr><w:spacing w:before="130" w:after="50"/></w:pPr><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>单元格</w:t></w:r><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>2</w:t></w:r></w:p></w:tc><w:tc><w:tcPr><w:tcW w:w="15" w:type="pct"/></w:tcPr><w:p w:rsidR="001272E8" w:rsidRDefault="00EC6803"><w:pPr><w:spacing w:before="130" w:after="50"/><w:jc w:val="center"/></w:pPr><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t></w:t></w:r></w:p></w:tc><w:tc><w:tcPr><w:tcW w:w="45" w:type="pct"/></w:tcPr><w:p w:rsidR="001272E8" w:rsidRDefault="00EC6803"><w:pPr><w:spacing w:before="130" w:after="50"/></w:pPr><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>单元格</w:t></w:r><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>4</w:t></w:r></w:p></w:tc></w:tr><w:tr w:rsidR="001272E8"><w:tc><w:tcPr><w:tcW w:w="25" w:type="pct"/></w:tcPr><w:p w:rsidR="001272E8" w:rsidRDefault="00EC6803"><w:pPr><w:spacing w:before="130" w:after="50"/></w:pPr><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>单元格</w:t></w:r><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>1</w:t></w:r></w:p></w:tc><w:tc><w:tcPr><w:tcW w:w="15" w:type="pct"/></w:tcPr><w:p w:rsidR="001272E8" w:rsidRDefault="00EC6803"><w:pPr><w:spacing w:before="130" w:after="50"/></w:pPr><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>单元格</w:t></w:r><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>2</w:t></w:r></w:p></w:tc><w:tc><w:tcPr><w:tcW w:w="15" w:type="pct"/></w:tcPr><w:p w:rsidR="001272E8" w:rsidRDefault="00EC6803"><w:pPr><w:spacing w:before="130" w:after="50"/><w:jc w:val="center"/></w:pPr><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t></w:t></w:r></w:p></w:tc><w:tc><w:tcPr><w:tcW w:w="45" w:type="pct"/></w:tcPr><w:p w:rsidR="001272E8" w:rsidRDefault="00EC6803"><w:pPr><w:spacing w:before="130" w:after="50"/></w:pPr><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>单元格</w:t></w:r><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>4</w:t></w:r></w:p></w:tc></w:tr></w:tbl>

然后看java的实现。
通过ObjectFactory生成Tbl、Tr、Tc等对象,然后将这些对象进行关联,最后将表格Tbl对象写入到word中。

    public static void wordTable(WordprocessingMLPackage wPackage) {// 生成参数表格ObjectFactory objectFactory = Context.getWmlObjectFactory();Tbl table = objectFactory.createTbl();// 标题行 处理Tr tr = objectFactory.createTr();wordTc(tr, WordUtil.getPByStyleId("单元格1", WHQ_3), A41);wordTc(tr, WordUtil.getPByStyleId("单元格2", WHQ_3), A42);wordTc(tr, WordUtil.getPByStyleId("单元格3", WHQ_3), A43);wordTc(tr, WordUtil.getPByStyleId("单元格4", WHQ_3), A44);table.getContent().add(tr);// 数据行 处理,测试添加3条数据for (int i = 0; i < 3; i++) {Tr trTemp = objectFactory.createTr();wordTc(trTemp, WordUtil.getPByStyleId("单元格1", WHQ_4), A51);wordTc(trTemp, WordUtil.getPByStyleId("单元格2", WHQ_4), A52);wordTc(trTemp, WordUtil.getPByStyleId("是", WHQ_5), A53);wordTc(trTemp, WordUtil.getPByStyleId("单元格4", WHQ_4), A54);table.getContent().add(trTemp);}// 表格整体样式Style tabStyle3 = WordStylesUtil.getStyleById(A3);table.setTblPr(new TblPr());// 边框线处理table.getTblPr().setTblBorders(tabStyle3.getTblPr().getTblBorders());// 表格列长度固定不可变table.getTblPr().setTblLayout(tabStyle3.getTblPr().getTblLayout());// 表格写入word文件wPackage.getMainDocumentPart().getContent().add(table);}public static void wordTc(Tr tr, P p, String tcStyleId) {ObjectFactory objectFactory = Context.getWmlObjectFactory();Tc tc = objectFactory.createTc();tc.setTcPr(WordStylesUtil.getStyleById(tcStyleId).getTcPr());tc.getContent().add(p);tr.getContent().add(tc);}

2.8、超链接

示例给出的超链接为word文档内部的超链接。而且是将整个段落作为超链接进行处理。
还是先看word文档解压后的document.xml文件中的超链接内容。
为了在word文档中看到超链接跳转的效果。此处加了一个分页。
从以下xml代码中可以看到。段落的超链接是嵌套在段落中的w:hyperlink标签控制的,w:hyperlink标签中的w:anchor属性为“锚点”。与跳转目标要匹配一致才可以成功跳转,可以看到锚点目标使用w:bookmarkStart标签,其中的w:name属性与w:hyperlink标签中的w:anchor属性一致。
w:hyperlink标签中的w:history属性也很重要,当我们跳转到目标地方后,如果想通过快捷键alt + ⬅返回上一次的位置,则此属性必须设置为true。

        <w:p><w:pPr><w:spacing w:before="130" w:after="50"/></w:pPr><w:hyperlink w:history="true" w:anchor="_8418a746ee1a10cd44e530fdbcee6469"><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000" w:themeColor="hyperlink"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t xml:space="preserve">超链接1</w:t></w:r></w:hyperlink></w:p><w:p><w:r><w:br w:type="page"/></w:r></w:p><w:p><w:pPr><w:spacing w:after="50" w:line="312" w:lineRule="auto"/></w:pPr><w:r><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:b/><w:bCs/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr><w:t>超链接2</w:t></w:r><w:bookmarkStart w:name="_8418a746ee1a10cd44e530fdbcee6469" w:id="1"/><w:bookmarkEnd w:id="1"/></w:p>

java代码实现。
超链接起始位置。

    /*** 生成超链接段落(调用锚点)。整个段落都是超链接。** @param paragraphText* @param anchor        超链接跳转锚点标识* @param styleId* @return org.docx4j.wml.P*/public static P createHyperlinkConsume(String paragraphText, String anchor, String styleId) {ObjectFactory factory = Context.getWmlObjectFactory();P p = factory.createP();P.Hyperlink pHyperlink = factory.createPHyperlink();pHyperlink.setAnchor("_" + getAnchor(anchor));// ctrl跳转后,按alt + ⬅ 可以跳转回来。以下参数必须为true,否则光标返回位置不对。pHyperlink.setHistory(true);Style style = WordStylesUtil.getStyleById(styleId);addRun(pHyperlink, paragraphText, style);p.getContent().add(pHyperlink);p.setPPr(style.getPPr());return p;}

超链接目标位置。

    /*** 生成超链接段落(锚点)** @param paragraphText* @param anchor* @param styleId* @return org.docx4j.wml.P*/public static P createHyperlinkProduce(String paragraphText, String anchor, String styleId) {P p = getPByStyleId(paragraphText, styleId);ObjectFactory objectFactory = Context.getWmlObjectFactory();// 创建一个超链接对象BigInteger hli = BigInteger.valueOf(getHyperlinkId());CTBookmark ctBookmark = new CTBookmark();ctBookmark.setId(hli);ctBookmark.setName("_" + getAnchor(anchor));JAXBElement<CTBookmark> pHyperlinkBookmarkStart = objectFactory.createPHyperlinkBookmarkStart(ctBookmark);p.getContent().add(pHyperlinkBookmarkStart);CTMarkupRange ctMarkupRange = new CTMarkupRange();ctMarkupRange.setId(hli);objectFactory.createPBookmarkEnd(ctMarkupRange);p.getContent().add(ctMarkupRange);return p;}

2.9、写入样式及文件保存

最后一定要将样式写入word文档,否则样式都不生效。

        // 写入word文档样式信息wPackage.getMainDocumentPart().getStyleDefinitionsPart().getJaxbElement().getStyle().addAll(WordStylesUtil.STYLES.values());wPackage.save(outputFile);

总结

此篇文章只是从word的使用中挑选了部分功能进行说明。如果以上功能没有你想要的结果。可以自己摸索实现。首先你要新建一个word文档,然后将你要的功能写进去,之后将word文档后缀重命名为zip并解压缩,最后你就得到了xml文件,打开xml文件查看其中的xml实现(word目录下的document.xml),或者你想要某种样式,可以查看word目录下的styles.xml。

最后给出示例中的所有java源码。

示例源码

在这里插入图片描述

样式xml

<?xml version="1.0" encoding="UTF-8"?>
<w:styles xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"><w:docDefaults><w:rPrDefault><w:rPr><w:rFonts w:asciiTheme="minorHAnsi" w:hAnsiTheme="minorHAnsi" w:eastAsiaTheme="minorHAnsi" w:cstheme="minorBidi"/><w:sz w:val="22"/><w:szCs w:val="22"/><w:lang w:val="en-US" w:eastAsia="en-US" w:bidi="ar-SA"/></w:rPr></w:rPrDefault><w:pPrDefault><w:pPr><w:spacing w:after="200" w:line="276" w:lineRule="auto"/></w:pPr></w:pPrDefault></w:docDefaults><w:latentStyles w:defLockedState="false" w:defUIPriority="99" w:defSemiHidden="true" w:defUnhideWhenUsed="true" w:defQFormat="false" w:count="267"><w:lsdException w:name="Normal" w:uiPriority="0" w:semiHidden="false" w:unhideWhenUsed="false" w:qFormat="true"/><w:lsdException w:name="heading 1" w:uiPriority="9" w:semiHidden="false" w:unhideWhenUsed="false" w:qFormat="true"/><w:lsdException w:name="heading 2" w:uiPriority="9" w:qFormat="true"/><w:lsdException w:name="heading 3" w:uiPriority="9" w:qFormat="true"/><w:lsdException w:name="heading 4" w:uiPriority="9" w:qFormat="true"/></w:latentStyles><w:style w:type="paragraph" w:styleId="Normal" w:default="true"><w:name w:val="Normal"/><w:qFormat/><w:rsid w:val="004A3277"/></w:style><w:style w:type="paragraph" w:styleId="Heading1"><w:name w:val="heading 1"/><w:basedOn w:val="Normal"/><w:next w:val="Normal"/><w:link w:val="Heading1Char"/><w:uiPriority w:val="9"/><w:qFormat/><w:rsid w:val="00841CD9"/><w:pPr><w:pStyle w:val="Heading1"/><w:keepNext/><w:keepLines/><w:spacing w:before="480"/><w:outlineLvl w:val="0"/></w:pPr><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:b/><w:bCs/><w:color w:val="000000"/><w:sz w:val="42"/><w:szCs w:val="28"/></w:rPr></w:style><w:style w:type="paragraph" w:styleId="Heading2"><w:name w:val="heading 2"/><w:basedOn w:val="Normal"/><w:next w:val="Normal"/><w:link w:val="Heading2Char"/><w:uiPriority w:val="9"/><w:unhideWhenUsed/><w:qFormat/><w:rsid w:val="00841CD9"/><w:pPr><w:pStyle w:val="Heading2"/><w:keepNext/><w:keepLines/><w:spacing w:before="200"/><w:outlineLvl w:val="1"/></w:pPr><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:b/><w:bCs/><w:color w:val="000000"/><w:sz w:val="38"/><w:szCs w:val="26"/></w:rPr></w:style><w:style w:type="paragraph" w:styleId="Heading3"><w:name w:val="heading 3"/><w:basedOn w:val="Normal"/><w:next w:val="Normal"/><w:link w:val="Heading3Char"/><w:uiPriority w:val="9"/><w:unhideWhenUsed/><w:qFormat/><w:rsid w:val="00841CD9"/><w:pPr><w:keepNext/><w:keepLines/><w:spacing w:before="200"/><w:outlineLvl w:val="2"/></w:pPr><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:b/><w:bCs/><w:color w:val="000000"/><w:sz w:val="34"/></w:rPr></w:style><w:style w:type="paragraph" w:styleId="Heading4"><w:name w:val="heading 4"/><w:basedOn w:val="Normal"/><w:next w:val="Normal"/><w:link w:val="Heading4Char"/><w:uiPriority w:val="9"/><w:unhideWhenUsed/><w:qFormat/><w:rsid w:val="00841CD9"/><w:pPr><w:keepNext/><w:keepLines/><w:spacing w:before="200"/><w:outlineLvl w:val="3"/></w:pPr><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:b/><w:bCs/><w:color w:val="000000"/><w:sz w:val="30"/></w:rPr></w:style><w:style w:type="paragraph" w:styleId="Heading5"><w:name w:val="heading 5"/><w:basedOn w:val="Normal"/><w:next w:val="Normal"/><w:link w:val="Heading5Char"/><w:uiPriority w:val="9"/><w:unhideWhenUsed/><w:qFormat/><w:rsid w:val="00841CD9"/><w:pPr><w:keepNext/><w:keepLines/><w:spacing w:before="200"/><w:outlineLvl w:val="4"/></w:pPr><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:b/><w:bCs/><w:color w:val="000000"/><w:sz w:val="28"/></w:rPr></w:style><w:style w:type="paragraph" w:styleId="ne-codeblock"/><!-- 正文段落 加粗 居左 --><w:style w:type="paragraph" w:styleId="whq1" w:customStyle="true"><w:name w:val="whq1"/><w:uiPriority w:val="9"/><w:rsid w:val="00841CD9"/><w:pPr><w:spacing w:after="50" w:line="312" w:lineRule="auto"/></w:pPr><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:b/><w:bCs/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr></w:style><!-- 正文段落 不加粗 居左 --><w:style w:type="paragraph" w:styleId="whq2" w:customStyle="true"><w:name w:val="whq2"/><w:uiPriority w:val="9"/><w:rsid w:val="00841CD9"/><w:pPr><w:spacing w:after="50" w:line="312" w:lineRule="auto"/></w:pPr><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr></w:style><!-- 正文段落 加粗 居中,表格单元格,表头使用 --><w:style w:type="paragraph" w:styleId="whq3" w:customStyle="true"><w:name w:val="whq3"/><w:uiPriority w:val="9"/><w:rsid w:val="00841CD9"/><w:pPr><w:spacing w:before="130" w:after="50"/><w:jc w:val="center"/></w:pPr><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:b/><w:bCs/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr></w:style><!-- 正文段落 不加粗 居左 增加段前间距,表格单元格使用 --><w:style w:type="paragraph" w:styleId="whq4" w:customStyle="true"><w:name w:val="whq4"/><w:uiPriority w:val="9"/><w:rsid w:val="00841CD9"/><w:pPr><w:spacing w:before="130" w:after="50"/></w:pPr><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr></w:style><!-- 正文段落 不加粗 居左 增加段前间距,表格单元格使用 添加超链接样式 --><w:style w:type="paragraph" w:styleId="whq41" w:customStyle="true"><w:name w:val="whq41"/><w:uiPriority w:val="9"/><w:rsid w:val="00841CD9"/><w:pPr><w:spacing w:before="130" w:after="50"/></w:pPr><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000" w:themeColor="hyperlink"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr></w:style><!-- 正文段落 不加粗 居中 增加段前间距,表格单元格使用 --><w:style w:type="paragraph" w:styleId="whq5" w:customStyle="true"><w:name w:val="whq5"/><w:uiPriority w:val="9"/><w:rsid w:val="00841CD9"/><w:pPr><w:spacing w:before="130" w:after="50"/><w:jc w:val="center"/></w:pPr><w:rPr><w:rFonts w:ascii="宋体" w:eastAsia="宋体"/><w:color w:val="000000"/><w:sz w:val="24"/><w:szCs w:val="24"/></w:rPr></w:style><w:style w:type="table" w:default="1" w:styleId="a1"><w:name w:val="Normal Table"/><w:uiPriority w:val="99"/><w:semiHidden/><w:unhideWhenUsed/><w:tblPr><w:tblInd w:w="0" w:type="dxa"/><w:tblCellMar><w:top w:w="0" w:type="dxa"/><w:left w:w="108" w:type="dxa"/><w:bottom w:w="0" w:type="dxa"/><w:right w:w="108" w:type="dxa"/></w:tblCellMar></w:tblPr></w:style><!-- 表格:边框线、列长度固定不可变--><w:style w:type="table" w:styleId="a3"><w:name w:val="Table Grid"/><w:basedOn w:val="a1"/><w:uiPriority w:val="39"/><w:rsid w:val="00A76ABD"/><w:tblPr><w:tblBorders><w:top w:val="single" w:sz="4" w:space="0" w:color="auto"/><w:left w:val="single" w:sz="4" w:space="0" w:color="auto"/><w:bottom w:val="single" w:sz="4" w:space="0" w:color="auto"/><w:right w:val="single" w:sz="4" w:space="0" w:color="auto"/><w:insideH w:val="single" w:sz="4" w:space="0" w:color="auto"/><w:insideV w:val="single" w:sz="4" w:space="0" w:color="auto"/></w:tblBorders><w:tblCellMar><w:top w:w="0" w:type="dxa"/><w:left w:w="108" w:type="dxa"/><w:bottom w:w="0" w:type="dxa"/><w:right w:w="108" w:type="dxa"/></w:tblCellMar><w:tblW w:w="0" w:type="auto"/><w:tblLayout w:type="fixed"/></w:tblPr></w:style><!-- 表格:表头样式,添加背景色 --><w:style w:type="table" w:styleId="a41"><w:name w:val="Table Grid"/><w:basedOn w:val="a3"/><w:uiPriority w:val="39"/><w:rsid w:val="00A76ABD"/><w:trPr><w:trHeight w:val="100"/></w:trPr><w:tcPr><!--<w:tcW w:w="2376" w:type="dxa"/>--><w:tcW w:w="25" w:type="pct"/><w:shd w:val="clear" w:color="auto" w:fill="9CC2E5" w:themeFill="accent1" w:themeFillTint="99"/></w:tcPr></w:style><w:style w:type="table" w:styleId="a42"><w:name w:val="Table Grid"/><w:basedOn w:val="a3"/><w:uiPriority w:val="39"/><w:rsid w:val="00A76ABD"/><w:trPr><w:trHeight w:val="100"/></w:trPr><w:tcPr><!--<w:tcW w:w="1276" w:type="dxa"/>--><w:tcW w:w="15" w:type="pct"/><w:shd w:val="clear" w:color="auto" w:fill="9CC2E5" w:themeFill="accent1" w:themeFillTint="99"/></w:tcPr></w:style><w:style w:type="table" w:styleId="a43"><w:name w:val="Table Grid"/><w:basedOn w:val="a3"/><w:uiPriority w:val="39"/><w:rsid w:val="00A76ABD"/><w:trPr><w:trHeight w:val="100"/></w:trPr><w:tcPr><!--<w:tcW w:w="1276" w:type="dxa"/>--><w:tcW w:w="15" w:type="pct"/><w:shd w:val="clear" w:color="auto" w:fill="9CC2E5" w:themeFill="accent1" w:themeFillTint="99"/></w:tcPr></w:style><w:style w:type="table" w:styleId="a44"><w:name w:val="Table Grid"/><w:basedOn w:val="a3"/><w:uiPriority w:val="39"/><w:rsid w:val="00A76ABD"/><w:trPr><w:trHeight w:val="100"/></w:trPr><w:tcPr><!--<w:tcW w:w="4315" w:type="dxa"/>--><w:tcW w:w="45" w:type="pct"/><w:shd w:val="clear" w:color="auto" w:fill="9CC2E5" w:themeFill="accent1" w:themeFillTint="99"/></w:tcPr></w:style><!-- 表格:其他单元格,默认样式 --><w:style w:type="table" w:styleId="a51"><w:name w:val="Table Grid"/><w:basedOn w:val="a3"/><w:uiPriority w:val="39"/><w:rsid w:val="00A76ABD"/><w:trPr><w:trHeight w:val="416"/></w:trPr><w:tcPr><!--<w:tcW w:w="2376" w:type="dxa"/>--><w:tcW w:w="25" w:type="pct"/></w:tcPr></w:style><w:style w:type="table" w:styleId="a52"><w:name w:val="Table Grid"/><w:basedOn w:val="a3"/><w:uiPriority w:val="39"/><w:rsid w:val="00A76ABD"/><w:trPr><w:trHeight w:val="416"/></w:trPr><w:tcPr><!--<w:tcW w:w="1276" w:type="dxa"/>--><w:tcW w:w="15" w:type="pct"/></w:tcPr></w:style><w:style w:type="table" w:styleId="a53"><w:name w:val="Table Grid"/><w:basedOn w:val="a3"/><w:uiPriority w:val="39"/><w:rsid w:val="00A76ABD"/><w:trPr><w:trHeight w:val="416"/></w:trPr><w:tcPr><!--<w:tcW w:w="1276" w:type="dxa"/>--><w:tcW w:w="15" w:type="pct"/></w:tcPr></w:style><w:style w:type="table" w:styleId="a54"><w:name w:val="Table Grid"/><w:basedOn w:val="a3"/><w:uiPriority w:val="39"/><w:rsid w:val="00A76ABD"/><w:trPr><w:trHeight w:val="416"/></w:trPr><w:tcPr><!--<w:tcW w:w="4315" w:type="dxa"/>--><w:tcW w:w="45" w:type="pct"/></w:tcPr></w:style>
</w:styles>

WordConstant

package com.demo.word;public class WordConstant {public final static String NORMAL = "Normal";// 一级标题public final static String HEADING_1 = "Heading1";// 二级标题public final static String HEADING_2 = "Heading2";// 正文段落 加粗 居左public final static String WHQ_1 = "whq1";// 正文段落 不加粗 居左public final static String WHQ_2 = "whq2";// 正文段落 加粗 居中,表格单元格,表头使用public final static String WHQ_3 = "whq3";// 正文段落 不加粗 居左 增加段前间距,表格单元格使用public final static String WHQ_4 = "whq4";// 正文段落 不加粗 居左 增加段前间距,表格单元格使用,添加超链接样式public final static String WHQ_41 = "whq41";// 正文段落 不加粗 居中 增加段前间距,表格单元格使用public final static String WHQ_5 = "whq5";// 表格:边框线、列长度固定不可变public final static String A3 = "a3";// 表格:表头样式,添加背景色,宽度25public final static String A41 = "a41";// 表格:表头样式,添加背景色,宽度15public final static String A42 = "a42";// 表格:表头样式,添加背景色,宽度15public final static String A43 = "a43";// 表格:表头样式,添加背景色,宽度45public final static String A44 = "a44";// 表格:其他单元格,默认样式,宽度25public final static String A51 = "a51";// 表格:其他单元格,默认样式,宽度15public final static String A52 = "a52";// 表格:其他单元格,默认样式,宽度15public final static String A53 = "a53";// 表格:其他单元格,默认样式,宽度45public final static String A54 = "a54";
}

WordStylesUtil

package com.demo.word;import cn.hutool.core.collection.CollectionUtil;
import org.docx4j.XmlUtils;
import org.docx4j.wml.Style;
import org.docx4j.wml.Styles;import javax.xml.bind.JAXBException;
import java.io.InputStream;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;public class WordStylesUtil {// 正文样式IDpublic static final String NORMAL_STYLE = "Normal";private WordStylesUtil() {try {InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream("styles.xml");Styles styles = (Styles) XmlUtils.unmarshal(resourceAsStream);if (styles != null && !CollectionUtil.isEmpty(styles.getStyle())) {STYLES = styles.getStyle().stream().collect(Collectors.toMap(Style::getStyleId, Function.identity(), (oldVal, newVal) -> newVal));}} catch (JAXBException e) {System.err.println("加载styles.xml异常!");System.err.println(e);}}private static WordStylesUtil wordStylesUtil = new WordStylesUtil();public static Map<String, Style> STYLES;private static WordStylesUtil getInstance() {if (wordStylesUtil == null) {wordStylesUtil = new WordStylesUtil();}return wordStylesUtil;}/*** 通过样式ID获取Style** @param styleId* @return org.docx4j.wml.Style*/public static Style getStyleById(String styleId) {getInstance();return STYLES.get(styleId);}
}

WordUtil

package com.demo.word;import cn.hutool.crypto.digest.MD5;
import com.sun.org.apache.xerces.internal.impl.xs.SchemaSymbols;
import org.apache.commons.lang3.StringUtils;
import org.docx4j.jaxb.Context;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import org.docx4j.wml.*;
import org.jvnet.jaxb2_commons.ppp.Child;import javax.xml.bind.JAXBElement;
import java.io.File;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;public class WordUtil {// word 超链接IDprivate static Integer hyperlinkId = 0;/*** 获取超链接ID,每次自增1** @param* @return java.lang.Integer*/public static Integer getHyperlinkId() {return ++hyperlinkId;}/*** 创建docx文档* 原文件如果已经存在的情况下,原文件中的内容会被清空* 在windows中,只要是相同后缀名且前缀也相同就是同一文件(不区分大小写),当是同一后缀名且大小写不一致时,已存在的文件后缀名大小写不会改动* 如果原文件已存在,则该word文件不能处于打开状态** @param docxFile* @return void*/public static void createDocx(File docxFile) throws Exception {// Create the package 建包WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();// 另存为新的文件 保存// 如果原文件已存在的话,里面的内容会被清空wordMLPackage.save(docxFile);}/*** 添加段落,整个段落使用同一种样式** @param wPackage* @param paragraphText* @param styleId* @return void*/public static void insertOneParagraph(WordprocessingMLPackage wPackage, String paragraphText, String styleId) {if (StringUtils.isBlank(paragraphText)) {return;}MainDocumentPart mdt = wPackage.getMainDocumentPart();Style style = WordStylesUtil.getStyleById(styleId);if (style == null) {// 未查询到样式,直接添加默认段落mdt.addParagraphOfText(paragraphText);} else {mdt.getContent().add(getPByStyleId(paragraphText, styleId));}}/*** 根据样式ID获取段落对象P** @param paragraphText* @param styleId* @return org.docx4j.wml.P*/public static P getPByStyleId(String paragraphText, String styleId) {Style style = WordStylesUtil.getStyleById(styleId);ObjectFactory factory = Context.getWmlObjectFactory();P paragraph = factory.createP();R run = factory.createR();run.setRPr(style.getRPr());String[] split = paragraphText == null ? new String[0] : paragraphText.split("\n");if (split.length > 1) {List<Child> list = new ArrayList<>();for (String s : split) {Text text = factory.createText();text.setValue(s);// 保留前后空格text.setSpace(SchemaSymbols.ATTVAL_PRESERVE);// 将换行符进行处理为</Br>Br br = factory.createBr();list.add(text);list.add(br);}run.getContent().addAll(list);} else {Text text = factory.createText();text.setValue(paragraphText);run.getContent().add(text);}paragraph.getContent().add(run);paragraph.setPPr(style.getPPr());return paragraph;}/*** 添加段落,可以是复合样式的段落** @param wPackage* @param paragraph 用户自定义好的段落(包括样式与内容)* @return void*/public static void insertOneParagraph(WordprocessingMLPackage wPackage, P paragraph) {wPackage.getMainDocumentPart().getContent().add(paragraph);}/*** 给word中写入复合样式的段落信息** @param wPackage* @param context   二维数组,二维中的数据只能有两个元素,第一个为段落内容,第二个为样式ID。例如:[["内容1","样式1"],["内容2","样式2"]]*/public static void complexPWrite(WordprocessingMLPackage wPackage, String[][] context) {if (context.length <= 0) {return;}P complexP = WordUtil.getComplexP();for (int i = 0; i < context.length; i++) {String[] temp = context[i];if (temp.length != 2) {continue;}String paragraph = temp[0];String styleId = temp[1];Style style = WordStylesUtil.getStyleById(styleId);if (StringUtils.isBlank(paragraph) || style == null) {continue;}addRun(complexP, paragraph, style);}// 写入insertOneParagraph(wPackage, complexP);}/*** 给word中写入复合样式的段落信息** @param wPackage* @param prefix            前缀* @param prefixStyleId     正文段落 加粗 居左  样式ID* @param text              内容* @param textStyleId       正文段落 不加粗 居左 样式ID*/public static void complexPWrite(WordprocessingMLPackage wPackage,  String prefix, String prefixStyleId,String text, String textStyleId) {String[][] context = new String[2][2];context[0][0] = prefix;context[0][1] = prefixStyleId;context[1][0] = text;context[1][1] = textStyleId;complexPWrite(wPackage, context);}/*** 复合段落某一段数据处理** @param paragraph         整个段落* @param paragraphText     当前处理的某段数据* @param style             样式* @return void*/public static void addRun(P paragraph, String paragraphText, Style style) {ObjectFactory factory = Context.getWmlObjectFactory();Text text = factory.createText();text.setValue(paragraphText);// 保留前后空格text.setSpace(SchemaSymbols.ATTVAL_PRESERVE);R run = factory.createR();run.getContent().add(text);run.setRPr(style.getRPr());paragraph.getContent().add(run);}/*** 某一段数据处理-添加超链接** @param pHyperlink* @param paragraphText* @param style* @return void*/public static void addRun(P.Hyperlink pHyperlink, String paragraphText, Style style) {ObjectFactory factory = Context.getWmlObjectFactory();Text text = factory.createText();text.setValue(paragraphText);// 保留前后空格text.setSpace(SchemaSymbols.ATTVAL_PRESERVE);R run = factory.createR();run.getContent().add(text);run.setRPr(style.getRPr());pHyperlink.getContent().add(run);}/*** 复合段落使用正文pPr(Previous Paragraph Properties)** @param* @return org.docx4j.wml.P*/public static P getComplexP() {ObjectFactory factory = Context.getWmlObjectFactory();P paragraph = factory.createP();Style style = WordStylesUtil.getStyleById(WordStylesUtil.NORMAL_STYLE);paragraph.setPPr(style.getPPr());return paragraph;}/*** 生成超链接段落(锚点)** @param paragraphText* @param anchor* @param styleId* @return org.docx4j.wml.P*/public static P createHyperlinkProduce(String paragraphText, String anchor, String styleId) {P p = getPByStyleId(paragraphText, styleId);ObjectFactory objectFactory = Context.getWmlObjectFactory();// 创建一个超链接对象BigInteger hli = BigInteger.valueOf(getHyperlinkId());CTBookmark ctBookmark = new CTBookmark();ctBookmark.setId(hli);ctBookmark.setName("_" + getAnchor(anchor));JAXBElement<CTBookmark> pHyperlinkBookmarkStart = objectFactory.createPHyperlinkBookmarkStart(ctBookmark);p.getContent().add(pHyperlinkBookmarkStart);CTMarkupRange ctMarkupRange = new CTMarkupRange();ctMarkupRange.setId(hli);objectFactory.createPBookmarkEnd(ctMarkupRange);p.getContent().add(ctMarkupRange);return p;}/*** 生成超链接段落(锚点)并写入word。整个段落都是超链接。* 超链接锚点anchor自定义** @param wPackage* @param paragraphText     超链接段落* @param anchor            超链接锚点* @param styleId* @return void*/public static void createHyperlinkProduce(WordprocessingMLPackage wPackage, String paragraphText, String anchor, String styleId) {insertOneParagraph(wPackage, createHyperlinkProduce(paragraphText, anchor, styleId));}/*** 生成超链接段落(锚点)并写入word。整个段落都是超链接。* 超链接锚点anchor与段落内容相同。** @param wPackage* @param paragraphText* @param styleId* @return void*/public static void createHyperlinkProduce(WordprocessingMLPackage wPackage, String paragraphText, String styleId) {insertOneParagraph(wPackage, createHyperlinkProduce(paragraphText, paragraphText, styleId));}/*** 生成超链接段落(调用锚点)。整个段落都是超链接。** @param paragraphText* @param anchor        超链接跳转锚点标识* @param styleId* @return org.docx4j.wml.P*/public static P createHyperlinkConsume(String paragraphText, String anchor, String styleId) {ObjectFactory factory = Context.getWmlObjectFactory();P p = factory.createP();P.Hyperlink pHyperlink = factory.createPHyperlink();pHyperlink.setAnchor("_" + getAnchor(anchor));// ctrl跳转后,按alt + ⬅ 可以跳转回来。以下参数必须为true,否则光标返回位置不对。pHyperlink.setHistory(true);Style style = WordStylesUtil.getStyleById(styleId);addRun(pHyperlink, paragraphText, style);p.getContent().add(pHyperlink);p.setPPr(style.getPPr());return p;}/*** 生成超链接段落(调用锚点)。整个段落都是超链接。* 超链接锚点anchor自定义** @param wPackage* @param paragraphText* @param anchor* @param styleId* @return void*/public static void createHyperlinkConsume(WordprocessingMLPackage wPackage, String paragraphText, String anchor, String styleId) {insertOneParagraph(wPackage, createHyperlinkConsume(paragraphText, anchor, styleId));}/*** 生成超链接段落(调用锚点)。整个段落都是超链接。* 超链接锚点anchor与段落内容相同。** @param wPackage* @param paragraphText* @param styleId* @return void*/public static void createHyperlinkConsume(WordprocessingMLPackage wPackage, String paragraphText, String styleId) {insertOneParagraph(wPackage, createHyperlinkConsume(paragraphText, paragraphText, styleId));}/*** 超链接锚点处理。* 锚点不能含有某些特殊字符,此处使用MD5进行转换。** @param anchor* @return java.lang.String*/public static String getAnchor(String anchor) {return MD5.create().digestHex(anchor, StandardCharsets.UTF_8);}/*** 分页** @param wPackage* @return void*/public static void setPage(WordprocessingMLPackage wPackage) {ObjectFactory factory = Context.getWmlObjectFactory();P paragraph = factory.createP();Style style = WordStylesUtil.getStyleById(WordStylesUtil.NORMAL_STYLE);paragraph.setPPr(style.getPPr());// 创建换行,且类型设置为分页Br br = factory.createBr();br.setType(STBrType.PAGE);R run = factory.createR();run.setRPr(style.getRPr());run.getContent().add(br);paragraph.getContent().add(run);insertOneParagraph(wPackage, paragraph);}
}

Main

package com.demo.word;import org.docx4j.jaxb.Context;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.wml.*;import java.io.File;import static com.demo.word.WordConstant.*;public class Main {public static void main(String[] args) throws Exception {File outputFile = new File("C:\\Users\\admin\\Desktop\\test.docx");WordUtil.createDocx(outputFile);WordprocessingMLPackage wPackage = WordprocessingMLPackage.load(outputFile);// 写入一级标题WordUtil.insertOneParagraph(wPackage,"标题1", HEADING_1);// 写入单一样式段落WordUtil.insertOneParagraph(wPackage, "这是一个正文段落", NORMAL);// 写入复合样式段落WordUtil.complexPWrite(wPackage, "title:", WHQ_1, "测试title", WHQ_2);// 写入一个表格wordTable(wPackage);// 写入一个超链接(文档内部的超链接) 跳转起始处WordUtil.createHyperlinkConsume(wPackage,"超链接1", "这个必须唯一且与跳转的地方一致", WHQ_41);// 分页WordUtil.setPage(wPackage);// 写入一个超链接(文档内部的超链接) 跳转目标处WordUtil.createHyperlinkProduce(wPackage, "超链接2", "这个必须唯一且与跳转的地方一致", WHQ_1);// 写入word文档样式信息wPackage.getMainDocumentPart().getStyleDefinitionsPart().getJaxbElement().getStyle().addAll(WordStylesUtil.STYLES.values());wPackage.save(outputFile);}public static void wordTable(WordprocessingMLPackage wPackage) {// 生成参数表格ObjectFactory objectFactory = Context.getWmlObjectFactory();Tbl table = objectFactory.createTbl();// 标题行 处理Tr tr = objectFactory.createTr();wordTc(tr, WordUtil.getPByStyleId("单元格1", WHQ_3), A41);wordTc(tr, WordUtil.getPByStyleId("单元格2", WHQ_3), A42);wordTc(tr, WordUtil.getPByStyleId("单元格3", WHQ_3), A43);wordTc(tr, WordUtil.getPByStyleId("单元格4", WHQ_3), A44);table.getContent().add(tr);// 数据行 处理,测试添加3条数据for (int i = 0; i < 3; i++) {Tr trTemp = objectFactory.createTr();wordTc(trTemp, WordUtil.getPByStyleId("单元格1", WHQ_4), A51);wordTc(trTemp, WordUtil.getPByStyleId("单元格2", WHQ_4), A52);wordTc(trTemp, WordUtil.getPByStyleId("是", WHQ_5), A53);wordTc(trTemp, WordUtil.getPByStyleId("单元格4", WHQ_4), A54);table.getContent().add(trTemp);}// 表格整体样式Style tabStyle3 = WordStylesUtil.getStyleById(A3);table.setTblPr(new TblPr());// 边框线处理table.getTblPr().setTblBorders(tabStyle3.getTblPr().getTblBorders());// 表格列长度固定不可变table.getTblPr().setTblLayout(tabStyle3.getTblPr().getTblLayout());// 表格写入word文件wPackage.getMainDocumentPart().getContent().add(table);}public static void wordTc(Tr tr, P p, String tcStyleId) {ObjectFactory objectFactory = Context.getWmlObjectFactory();Tc tc = objectFactory.createTc();tc.setTcPr(WordStylesUtil.getStyleById(tcStyleId).getTcPr());tc.getContent().add(p);tr.getContent().add(tc);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/10139.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows Server 2012 R2 新增D盘分区

我们经常搭建windows版本的游戏时会要在D盘上操作&#xff0c;今天就介绍下新的服务器如何新增一个D盘。 在"开始"图标右边有个”服务器管理器“&#xff0c;单击点开 点开服务器管理器后&#xff0c;点击“工具”打开“计算机管理” 打开计算机管理后点击“存储”-…

QT切换控件布局

1、切换前垂直布局 2、切换后水平布局 3、关键代码 qDebug() << "开始切换布局";QWidget *widget centralWidget();QLayout *layout widget->layout();if(layout){while(layout->count()){QLayoutItem *item layout->takeAt(0);if(item->layout…

【DDR 终端稳压器】Sink and Source DDR Termination Regulator [C] S0 S1 S2 S3 S4 S5 6状态

TPS51200A-Q1 器件通过 EN 功能提供 S3 支持。EN引脚可以连接到终端应用中的SLP_S3信号。当EN 高电平&#xff08;S0 状态&#xff09;时&#xff0c;REFOUT 和 VO 引脚均导通。当EN 低电平&#xff08;S3状态&#xff09;时&#xff0c;VO引脚关断并通过内部放电MOSFET放电时…

决策树的学习(Decision Tree)

1.对于决策树的概念&#xff1a; **本质上&#xff1a;**决策树就是模拟树的结构基于 if-else的多层判断 2.目的&#xff1a; 对实例进行分类的树形结构&#xff0c;通过多层判断&#xff0c;将所提供的数据归纳为一种分类规则。 3.优点&#xff1a; 1.计算量小&#xff0c;…

源代码防泄密的重要性

​源代码”作为互联网企业的核心资产之一&#xff0c;其安全性至关重要。源代码泄露不仅可能导致企业丧失技术优势&#xff0c;还可能引发知识产权纠纷、增加竞争对手的市场竞争力&#xff0c;甚至可能被用于恶意目的&#xff0c;如开发恶意软件等。因此&#xff0c;保护源代码…

婉转之声舞台之梦

【婉转之声&#xff0c;舞台之梦】&#x1f3a4; 当旋律响起&#xff0c;每个音符承载着梦想与热情。#婉拒歌手# #歌手2024# 话题引爆网络&#xff0c;观众的期待值冲破天际&#xff0c;但谁才是那婉拒名单上的神秘巨星&#xff1f;[嘻嘻] 今夜&#xff0c;我们不谈已成的荣耀&…

QT的TcpServer

Server服务器端 QT版本5.6.1 界面设计 工程文件&#xff1a; 添加 network 模块 头文件引入TcpServer类和TcpSocket&#xff1a;QTcpServer和QTcpSocket #include <QTcpServer> #include <QTcpSocket>创建server对象并实例化&#xff1a; /*h文件中*/QTcpServer…

使用Django中的Session和Cookie来传递数据

在Django中&#xff0c;Session和Cookie是两种常用的机制&#xff0c;用于在服务器端和客户端之间传递数据。下面我将简要介绍如何在Django中使用Session和Cookie来传递数据。 1、问题背景 在 Django 中&#xff0c;可以使用 request.POST 来获取表单提交的数据。但是&#xf…

iOS plist文件增删改查

一. plist简介 plist文件&#xff0c;即属性列表文件&#xff0c;全名是Property List&#xff0c;这种文件的扩展名为.plist&#xff0c;因此&#xff0c;通常被叫做plist文件。它是一种用来存储串行化后的对象的文件&#xff0c;在iOS开发中通常用来存储用户设置&#xff0c…

GaussDB数据库SQL系列-复合查询

目录 一、前言 二、复合查询基础 三、实际应用示例 1、使用UNION合并查询结果 2、使用INTERSECT找出共同元素 3、使用EXCEPT排除特定结果 四、高级技巧 1、子查询实例 2、JOIN的应用 五、总结 一、前言 GaussDB是华为自主创新研发的分布式关系型数据库&#xff0c;具…

按键的短按、长按和连续的划分

在实际生活中&#xff0c;我们使用到的按键在短按、长按和按键松开时都会触发不同的功能。按键短按后松开和长按后松开的应用比短按和长按的应用较少&#xff0c;我了解的按键短按后松开和长按后松开的应用是在点动控制和长动控制中。这里主要讨论按键的短按、长按和连续这三种…

postgresql主从复制

用vmware 搭建的两台虚拟机 操作系统&#xff1a;Ubuntu 24.04 Server版 数据库&#xff1a;postgresql 16.2 主库&#xff1a;192.168.2.11 从库&#xff1a;192.168.2.12 如果遇到网络无法上网&#xff0c;可参考一下 Vmware 搭建的Ubuntu 24.04 网络配置-CSDN博客 1.两…

LED显示屏的部件组成及相关知识

LED显示屏作为现代化信息传播的重要载体&#xff0c;在各种场所得到了广泛应用。其功能强大&#xff0c;效果生动&#xff0c;但其背后的部件组成却是复杂而精密的。本文将介绍LED显示屏的主要部件组成及相关知识&#xff0c;以帮助读者更好地理解LED显示屏的工作原理和构造。 …

day07beef-xss之根据beef-xss获取cookies

1.安装 apt-get update apt-get install beef-xss 若报错运行不了尝试 apt remove ruby apt remove beef-xss apt-get install ruby apt-get install ruby-dev libpcap-dev gem install eventmachine apt-get install beef-xss 2.运行 beef-xss 运行成功会自动弹出浏览框。 攻…

提高Rust安装与更新的速度

一、背景 因为rust安装过程中&#xff0c;默认的下载服务器为crates.io&#xff0c;这是一个国外的服务器&#xff0c;国内用户使用时&#xff0c;下载与更新的速度非常慢&#xff0c;因此&#xff0c;我们需要使用一个国内的服务器来提高下载与更新的速度。 本文推荐使用字节…

企业微信集成H5授权登录相关知识(二)

流程&#xff1a; 1.前端请求企业微信获取code&#xff1a;官网网页授权链接 2.企业微信返回的code请求后端判断是否已绑定系统账户 3.后端根据企业微信code&#xff0c;accessToken获得userId 4.userId获取user进行oauth2授权方式进行免密登录 相关知识&#xff1a; 一&a…

SS-PEG-SS可以与多种底物进行反应,生成具有良好稳定性的键合结构

【试剂详情】 英文名称 SS-PEG-SS 中文名称 琥珀酰亚胺丁二酸酯-聚乙二醇-琥珀酰亚胺丁二酸酯 外观性状 由分子量决定&#xff0c;固体或者液体。 分子量 0.4k&#xff0c;0.6k&#xff0c;1k&#xff0c;2k&#xff0c;3.4k&#xff0c;5k&#xff0c;10k&#xff08;可…

初识多线程

1. 前置知识——进程 在学习多线程前需要了解操作系统中的基本知识&#xff0c;这里简单回顾下。 1.1 进程控制块 一个进程对应着一个进程控制块PCB&#xff0c;PCB是一个用于管理和维护进程信息的数据结构&#xff0c;这个数据结构中大致包含下面内容&#xff08;并不完整&…

金仓面对面 | 人大金仓×安硕信息共话金融信用风险管理数字化转型之道

金仓面对面 在数字化浪潮的推动下&#xff0c;人大金仓携手行业先锋&#xff0c;共同开启一场关于创新与转型的思想盛宴——金仓面对面。这不仅是一场对话&#xff0c;更是一次智慧的火花碰撞&#xff0c;一次行业数字化转型洞察的深度挖掘。 行业精英汇聚&#xff1a;我们荣幸…

云南区块链商户平台:抓包技术自制开票工具(二)

前言 上节我们分析了云南区块链商户平台的登录接口以及数据加密、解密&#xff0c;本节我们将构建一个项目框架&#xff0c;将大致的雏形制作出来 说明 由于我们使用开票软件都是在 云南区块链商户平台上操作&#xff0c;如果再开发电脑端就显得没必要&#xff0c;思考良久&…