【docx4j】docx4j操作docx,实现替换内容、转换pdf、html等操作

  主要是想要用此功插件操作docx,主要的操作就是操作段落等信息,另外,也想实现替换docx的内容,实现根据模板动态生成内容的效果,也想用此插件实现docx转换pdf。

  word的格式其实可以用xml来表现,docx4j也应该是基于xml来操作docx文档的。xml就比较好理解了。我们都是通过doc树的形式操作docx,只不过对于docx4j来说根节点是一个package,我们可以从根节点获取所有的内容,也可以指定元素的类型从document中查找元素集合,用下标访问指定位置的元素。

  docx4j官网下载的包本身缺slf4j的支持包,而且转换pdf的时候fop-2.3的包与docx4j的包冲突,在文章最后会将最终整理过的docx4j及其相关依赖包附上下载链接。

1.docx的下载

  到官网下载即可,下载的zip包里面有jar包,也有examples,下面的例子就是出自官网的examples。但是官网下载的lib里面日志记录缺失log4j的包和slf4j-log4j包。

  官网下载地址:https://www.docx4java.org/downloads.html

  

2.简单的使用

0.   docx4j.properties  可以指定docx的一些全局属性,包括文字方向,纸张大小等。下面是官网给出的一个配置

# Page size: use a value from org.docx4j.model.structure.PageSizePaper enum
# eg A4, LETTER
docx4j.PageSize=LETTER
# Page size: use a value from org.docx4j.model.structure.MarginsWellKnown enum
docx4j.PageMargins=NORMAL
docx4j.PageOrientationLandscape=false
# Page size: use a value from org.pptx4j.model.SlideSizesWellKnown enum
# eg A4, LETTER
pptx4j.PageSize=LETTER
pptx4j.PageOrientationLandscape=false
# These will be injected into docProps/app.xml
# if App.Write=true
docx4j.App.write=true
docx4j.Application=docx4j
docx4j.AppVersion=2.7
# of the form XX.YYYY where X and Y represent numerical values
# These will be injected into docProps/core.xml
docx4j.dc.write=true
docx4j.dc.creator.value=docx4j
docx4j.dc.lastModifiedBy.value=docx4j
#
#docx4j.McPreprocessor=true
# If you haven't configured log4j yourself
# docx4j will autoconfigure it. Set this to true to disable that
docx4j.Log4j.Configurator.disabled=false

 

 

1.创建一个新的docx文档

    /**
     * 创建一个简单的docx
     */
    private static void createDocx() {
        // Create the package
        WordprocessingMLPackage wordMLPackage;
        try {
            wordMLPackage = WordprocessingMLPackage.createPackage();
            // 另存为新的文件
            wordMLPackage.save(new File("C:/Users/liqiang/Desktop/docx4j/helloworld.docx"));
        } catch (InvalidFormatException e) {
            log.error("createDocx error:InvalidFormatException", e);
        } catch (Docx4JException e) {
            log.error("createDocx error: Docx4JException", e);
        }
    }

 

  调用  WordprocessingMLPackage.createPackage(); 创建一个包,并且调用其save(file)就是生成一个新的文件。

 

补充:还有另一种常用的保存方法是:

Docx4J.save(wordMLPackage, new File("C:/Users/liqiang/Desktop/docx4j/helloworld_2.docx"));

 

 

2.向文件中增加段落

    /**
     * 增加一个段落,增加完成记得保存,否则不生效
     */
    public static void addParagraph() {
        WordprocessingMLPackage wordprocessingMLPackage;
        try {
            wordprocessingMLPackage = WordprocessingMLPackage
                    .load(new File("C:/Users/liqiang/Desktop/docx4j/helloworld.docx"));
            wordprocessingMLPackage.getMainDocumentPart().addParagraphOfText("Hello Word!");
            wordprocessingMLPackage.getMainDocumentPart().addStyledParagraphOfText("Title", "Hello Word!");
            wordprocessingMLPackage.getMainDocumentPart().addStyledParagraphOfText("Subtitle", " a subtitle!");
            wordprocessingMLPackage.save(new File("C:/Users/liqiang/Desktop/docx4j/helloworld.docx"));
        } catch (Docx4JException e) {
            log.error("addParagraph to docx error: Docx4JException", e);
        }
    }

  调用  WordprocessingMLPackage.load(file)   加载一个已经存在的docx,最后记得调用其save方法进行保存,否则修改不生效。

 

最后文件内容:

【docx4j】docx4j操作docx,实现替换内容、转换pdf、html等操作_第1张图片

 

3.第二种采用工厂类增加段落的方法(工厂类的使用,工厂类也是一种通用的方法)

    /**
     * 增加一个段落,增加完成记得保存,否则不生效
     */
    public static void addParagraph2(String simpleText) {

        try {
            WordprocessingMLPackage wordprocessingMLPackage = WordprocessingMLPackage
                    .load(new File("C:/Users/liqiang/Desktop/docx4j/helloworld.docx"));
            org.docx4j.wml.ObjectFactory factory = Context.getWmlObjectFactory();
            org.docx4j.wml.P para = factory.createP();
            if (simpleText != null) {
                org.docx4j.wml.Text t = factory.createText();
                t.setValue(simpleText);
                org.docx4j.wml.R run = factory.createR();
                run.getContent().add(t);
                para.getContent().add(run);
            }
            wordprocessingMLPackage.getMainDocumentPart().getContent().add(para);
            wordprocessingMLPackage.save(new File("C:/Users/liqiang/Desktop/docx4j/helloworld.docx"));
        } catch (Exception e) {
            log.error("addParagraph to docx error: Docx4JException", e);
        }
    }

 先创建一个工厂,(需要导入的包是org.docx4j.wml,导错的的话下面全错)。

  R是一个运行块,负责便于将多个属性相同的Object对象统一操作,通过其内部的content成员变量可以添加内容,RPr是运行块的属性(属于类R的一个成员变量),可以对R对象进行操作。R通过被作为其他对象的content内容。所以通过R在A元素中加一个B元素的操作的一般步骤是:(1)创建R;(2)将内容元素B加到R中;(3)将R增加到A元素中;(4)将A元素加到mainDocumentPart内容中。

 

补充:工厂类的一些通用方法:

【docx4j】docx4j操作docx,实现替换内容、转换pdf、html等操作_第2张图片

 

 

4.读取文件的内容

    private static void readParagraph() {
        try {
            WordprocessingMLPackage wordprocessingMLPackage = WordprocessingMLPackage
                    .load(new File("C:/Users/liqiang/Desktop/docx4j/helloworld.docx"));

            String contentType = wordprocessingMLPackage.getContentType();
            log.info("contentType -> {}", contentType);

            MainDocumentPart mainDocumentPart = wordprocessingMLPackage.getMainDocumentPart();
            List content = mainDocumentPart.getContent();
            for (Object ob : content) {
                log.info("ob -> {}", ob);
            }
        } catch (Docx4JException e) {
            log.error("createDocx error: Docx4JException", e);
        }
    } 
    
   

 

结果:

2018-10-28 13:13:16 [cn.qlq.docx4j.Docx4jTest]-[INFO] contentType -> application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml2018-10-28 13:13:16 [cn.qlq.docx4j.Docx4jTest]-[INFO] ob -> Hello Word!
2018-10-28 13:13:16 [cn.qlq.docx4j.Docx4jTest]-[INFO] ob -> Hello Word!
2018-10-28 13:13:16 [cn.qlq.docx4j.Docx4jTest]-[INFO] ob ->  a subtitle!
2018-10-28 13:13:16 [cn.qlq.docx4j.Docx4jTest]-[INFO] ob -> Hello Word!
2018-10-28 13:13:16 [cn.qlq.docx4j.Docx4jTest]-[INFO] ob -> Hello Word!
2018-10-28 13:13:16 [cn.qlq.docx4j.Docx4jTest]-[INFO] ob ->  a subtitle!
2018-10-28 13:13:16 [cn.qlq.docx4j.Docx4jTest]-[INFO] ob -> Hello Word!
2018-10-28 13:13:16 [cn.qlq.docx4j.Docx4jTest]-[INFO] ob -> Hello Word!
2018-10-28 13:13:16 [cn.qlq.docx4j.Docx4jTest]-[INFO] ob ->  a subtitle!

 

 

 5.创建表格

(1)创建一个普通的表格

    public static void addTable() {
        try {
            WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
            ObjectFactory factory = Context.getWmlObjectFactory();
            MainDocumentPart mainDocumentPart = wordMLPackage.getMainDocumentPart();

            // 创建表格元素
            Tbl table = factory.createTbl();
            addBorders(table);

            for (int i = 0; i < 3; i++) {
                Tr tr = factory.createTr();
                for (int j = 0; j < 3; j++) {
                    Tc tc = factory.createTc();
                    P p = mainDocumentPart.createParagraphOfText("---row" + i + "---column" + j + "---");
                    tc.getContent().add(p);
                    tr.getContent().add(tc);

                }
                table.getContent().add(tr);
            }

            mainDocumentPart.addObject(table);
            wordMLPackage.save(new java.io.File("C:/Users/liqiang/Desktop/docx4j/helloworld.docx"));
        } catch (Docx4JException e) {
            log.error("createDocx error: Docx4JException", e);
        }

    }

 

 

查看createParagraphOfText(str)的源码:(1.创建一个text,并设置其值,2.创建一个R并将text增加到R中,3.创建一个P将R加到P中)

    public org.docx4j.wml.P createParagraphOfText(String simpleText) {
        
        org.docx4j.wml.ObjectFactory factory = Context.getWmlObjectFactory();
        org.docx4j.wml.P  para = factory.createP();

        if (simpleText!=null) {
            org.docx4j.wml.Text  t = factory.createText();
            t.setValue(simpleText);
    
            org.docx4j.wml.R  run = factory.createR();
            run.getContent().add(t); // ContentAccessor        
            
            para.getContent().add(run); // ContentAccessor
        }
        
        return para;
    }

 

 

结果:

【docx4j】docx4j操作docx,实现替换内容、转换pdf、html等操作_第3张图片

 

上面的表格创建出来了,但是表格的边框也没有,接下来研究更复杂的操作,包括显示边框,合并单元格,设置单元格样式。 

 

(2)显示表格的边框

public static void addTable() {
        try {
            WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
            ObjectFactory factory = Context.getWmlObjectFactory();
            MainDocumentPart mainDocumentPart = wordMLPackage.getMainDocumentPart();

            // 0. 创建表格元素
            Tbl table = factory.createTbl();

            // 1.显示表格的边框
            addBorders(table);

            // 2.添加表格内容(创建行和列)
            for (int i = 0; i < 3; i++) {
                Tr tr = factory.createTr();
                for (int j = 0; j < 3; j++) {
                    Tc tc = factory.createTc();
                    P p = mainDocumentPart.createParagraphOfText("---row" + i + "---column" + j + "---");//

                    tc.getContent().add(p);
                    tr.getContent().add(tc);

                }
                table.getContent().add(tr);
            }

            // 3.加表格加到主要内容中
            mainDocumentPart.addObject(table);
            wordMLPackage.save(new java.io.File("C:/Users/liqiang/Desktop/docx4j/helloworld.docx"));
        } catch (Docx4JException e) {
            log.error("createDocx error: Docx4JException", e);
        }
    }

    /**
     * 设置边框样式
     * 
     * @param table
     *            需要设置表格边框的单元格
     */
    private static void addBorders(Tbl table) {
        table.setTblPr(new TblPr());// 必须设置一个TblPr,否则最后会报空指针异常

        CTBorder border = new CTBorder();
        border.setColor("auto");
        border.setSz(new BigInteger("4"));
        border.setSpace(new BigInteger("0"));
        border.setVal(STBorder.SINGLE);

        TblBorders borders = new TblBorders();
        borders.setBottom(border);
        borders.setLeft(border);
        borders.setRight(border);
        borders.setTop(border);
        borders.setInsideH(border);
        borders.setInsideV(border);

        // 获取其内部的TblPr属性设置属性
        table.getTblPr().setTblBorders(borders);
    } 

结果:

 

(3)设置表格居中显示,而且内容部分字体加粗,设置列宽等操作

    public static void addTable() {
        try {
            WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
            ObjectFactory factory = Context.getWmlObjectFactory();
            MainDocumentPart mainDocumentPart = wordMLPackage.getMainDocumentPart();

            // 0. 创建表格元素
            Tbl table = factory.createTbl();

            // 1.显示表格的边框
            addBorders(table);

            // 2.添加表格内容(创建行和列)
            for (int i = 0; i < 3; i++) {
                Tr tr = factory.createTr();
                for (int j = 0; j < 3; j++) {
                    Tc tc = factory.createTc();

                    // P p = mainDocumentPart.createParagraphOfText("---row" + i
                    // + "---column" + j + "---");
                    // 第二种创建P并设置样式的方法
                    P p1 = factory.createP();
                    R r = factory.createR();
                    Text text = factory.createText();
                    text.setValue("---row" + i + "---column" + j + "---");

                    r.getContent().add(text);
                    p1.getContent().add(r);

                    // 2.1通过R设置字体加粗等属性
                    setRStyle(r);
                    // 2.2设置列宽
                    if (j == 1) {
                        setCellWidth(tc, 1250);
                    } else {
                        setCellWidth(tc, 2500);
                    }

                    tc.getContent().add(p1);
                    tr.getContent().add(tc);

                }
                table.getContent().add(tr);
            }

            // 3.合并单元格

            // 3.加表格加到主要内容中
            mainDocumentPart.addObject(table);
            wordMLPackage.save(new java.io.File("C:/Users/liqiang/Desktop/docx4j/helloworld.docx"));
        } catch (Docx4JException e) {
            log.error("createDocx error: Docx4JException", e);
        }
    }

    /**
     * 设置列宽
     * 
     * @param tc
     * @param width
     */
    private static void setCellWidth(Tc tc, int width) {
        TcPr tableCellProperties = new TcPr();
        TblWidth tableWidth = new TblWidth();
        tableWidth.setW(BigInteger.valueOf(width));
        tableCellProperties.setTcW(tableWidth);

        tc.setTcPr(tableCellProperties);
    }

    /**
     * 通过设置R设置表格中属性字体加粗,大小为25
     * 
     * @param
     */
    private static void setRStyle(R r) {
        // 1.创建一个RPr
        RPr rpr = new RPr();

        // 2.设置RPr
        // 2.1设置字体大小
        HpsMeasure size = new HpsMeasure();
        size.setVal(new BigInteger("25"));
        rpr.setSz(size);
        // 2.2设置加粗
        BooleanDefaultTrue bold = new BooleanDefaultTrue();
        bold.setVal(true);
        rpr.setB(bold);

        // 3.将RPr设置为R的属性
        r.setRPr(rpr);
    }

    /**
     * 设置边框样式
     * 
     * @param table
     *            需要设置表格边框的单元格
     */
    private static void addBorders(Tbl table) {
        table.setTblPr(new TblPr());// 必须设置一个TblPr,否则最后会报空指针异常

        CTBorder border = new CTBorder();
        border.setColor("auto");
        border.setSz(new BigInteger("4"));
        border.setSpace(new BigInteger("0"));
        border.setVal(STBorder.SINGLE);

        TblBorders borders = new TblBorders();
        borders.setBottom(border);
        borders.setLeft(border);
        borders.setRight(border);
        borders.setTop(border);
        borders.setInsideH(border);
        borders.setInsideV(border);

        // 获取其内部的TblPr属性设置属性
        table.getTblPr().setTblBorders(borders);
    }

 

结果:

【docx4j】docx4j操作docx,实现替换内容、转换pdf、html等操作_第4张图片

 

关于表格合并或者更加复杂的操作参考:https://www.cnblogs.com/cxxjohnson/p/7886275.html

 

6.读取表格内容:(解析docx4j的树结构---获取指定类型的元素)

表格内容:

 

 

代码:(有时候我们调用getContent()获取的元素类型是Tr之类的直接元素,可以强转;有时候不可以直接强转,其类型是JAXBElement,需要进行提取---getAllElementFromObject方法)

package cn.qlq.docx4j;

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;

import org.docx4j.TraversalUtil;
import org.docx4j.finders.ClassFinder;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import org.docx4j.wml.ContentAccessor;
import org.docx4j.wml.Tbl;
import org.docx4j.wml.Tc;
import org.docx4j.wml.Tr;

/**
 * 循环替换表格内容
 * 
 * @author QiaoLiQiang
 * @time 2018年10月28日下午8:51:41
 */
public class ReplaceTable {

    public static void main(String[] args) throws JAXBException {
        String template = "C:/Users/liqiang/Desktop/docx4j/helloworld_1.docx";
        WordprocessingMLPackage wordMLPackage;
        try {
            wordMLPackage = WordprocessingMLPackage.load(new java.io.File(template));
            MainDocumentPart documentPart = wordMLPackage.getMainDocumentPart();

            // 1. ClassFinder 构造类型查询器获取指定元素
            ClassFinder find = new ClassFinder(Tbl.class);
            new TraversalUtil(documentPart.getContent(), find);

            Tbl table = (Tbl) find.results.get(0);// 获取到第一个表格元素
            List trs = table.getContent();
            System.out.println(trs);
            System.out.println("=====================");

            for (Object obj : trs) {
                Tr tr = (Tr) obj;// 获取到tr
                List content = tr.getContent();
                System.out.println(content);
                List objList = getAllElementFromObject(tr, Tc.class);// 获取所有的Tc元素
                for (Object obj1 : objList) {
                    Tc tc = (Tc) obj1;
                    System.out.println(tc.getContent());
                }
                System.out.println("===============");
            }
        } catch (Docx4JException e) {
            e.printStackTrace();
        }
    }

    private static List getAllElementFromObject(Object obj, Class toSearch) {
        List result = new ArrayList();
        if (obj instanceof JAXBElement)
            obj = ((JAXBElement) obj).getValue();
        if (obj.getClass().equals(toSearch))
            result.add(obj);
        else if (obj instanceof ContentAccessor) {
            List children = ((ContentAccessor) obj).getContent();
            for (Object child : children) {
                result.addAll(getAllElementFromObject(child, toSearch));
            }
        }
        return result;
    }
} 
    
   

 结果:

[org.docx4j.wml.Tr@234f18c8, org.docx4j.wml.Tr@1de40494, org.docx4j.wml.Tr@64e89fe0, org.docx4j.wml.Tr@64585ee1, org.docx4j.wml.Tr@65bd393e, org.docx4j.wml.Tr@69f949a0]
=====================
[javax.xml.bind.JAXBElement@6d50ddba, javax.xml.bind.JAXBElement@580d1667, javax.xml.bind.JAXBElement@4339f15a]
[姓名]
[性别]
[年龄]
===============
[javax.xml.bind.JAXBElement@11146e31, javax.xml.bind.JAXBElement@544e5bb9, javax.xml.bind.JAXBElement@6467f9ec]
[name0]
[sex0]
[age0]
===============
[javax.xml.bind.JAXBElement@66492873, javax.xml.bind.JAXBElement@4cfeca7b, javax.xml.bind.JAXBElement@6b9f78ba]
[name1]
[sex1]
[age1]
===============
[javax.xml.bind.JAXBElement@32af3289, javax.xml.bind.JAXBElement@c1eda5e, javax.xml.bind.JAXBElement@3d925789]
[name2]
[sex2]
[age2]
===============
[javax.xml.bind.JAXBElement@52b102f3, javax.xml.bind.JAXBElement@6338c9ee, javax.xml.bind.JAXBElement@25515b26]
[name3]
[sex3]
[age3]
===============
[javax.xml.bind.JAXBElement@372eee, javax.xml.bind.JAXBElement@26ea0b5e, javax.xml.bind.JAXBElement@4f905c47]
[name4]
[sex4]
[age4]
===============

 

 

 

7.格式化样式的操作:

 有时候我们需要格式化一些样式,每个元素内部都有一个XXXpr属性用于操作样式,Pr表示Properties,如下:

【docx4j】docx4j操作docx,实现替换内容、转换pdf、html等操作_第5张图片

 

 

3.docx4j高级用法

1.docx转换为html

 参考github官网:https://github.com/plutext/docx4j/blob/master/src/samples/docx4j/org/docx4j/samples/ConvertOutHtml.java

package cn.qlq.docx4j;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;

import org.docx4j.Docx4J;
import org.docx4j.Docx4jProperties;
import org.docx4j.convert.out.HTMLSettings;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.samples.AbstractSample;

public class Docx2Html extends AbstractSample {

    static {

        inputfilepath = "C:/Users/liqiang/Desktop/docx4j/helloworld.docx";
        save = true;
        nestLists = true;
    }

    static boolean save;
    static boolean nestLists;

    public static void main(String[] args) throws Exception {
        WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage
                .load(new File("C:/Users/liqiang/Desktop/docx4j/helloworld.docx"));

        HTMLSettings htmlSettings = Docx4J.createHTMLSettings();

        htmlSettings.setImageDirPath(inputfilepath + "_files");
        htmlSettings.setImageTargetUri(inputfilepath.substring(inputfilepath.lastIndexOf("/") + 1) + "_files");
        htmlSettings.setWmlPackage(wordMLPackage);

        String userCSS = null;
        if (nestLists) {
            userCSS = "html, body, div, span, h1, h2, h3, h4, h5, h6, p, a, img,  table, caption, tbody, tfoot, thead, tr, th, td "
                    + "{ margin: 0; padding: 0; border: 0;}" + "body {line-height: 1;} ";
        } else {
            userCSS = "html, body, div, span, h1, h2, h3, h4, h5, h6, p, a, img,  ol, ul, li, table, caption, tbody, tfoot, thead, tr, th, td "
                    + "{ margin: 0; padding: 0; border: 0;}" + "body {line-height: 1;} ";

        }
        htmlSettings.setUserCSS(userCSS);

        OutputStream os;
        if (save) {
            os = new FileOutputStream(inputfilepath + ".html");
        } else {
            os = new ByteArrayOutputStream();
        }

        Docx4jProperties.setProperty("docx4j.Convert.Out.HTML.OutputMethodXML", true);

        Docx4J.toHTML(htmlSettings, os, Docx4J.FLAG_EXPORT_PREFER_XSL);

        if (save) {
            System.out.println("Saved: " + inputfilepath + ".html ");
        } else {
            System.out.println(((ByteArrayOutputStream) os).toString());
        }

        if (wordMLPackage.getMainDocumentPart().getFontTablePart() != null) {
            wordMLPackage.getMainDocumentPart().getFontTablePart().deleteEmbeddedFontTempFiles();
        }
        htmlSettings = null;
        wordMLPackage = null;
    }
}

 

 

 封装为一个更简单的工具类的代码如下:(userCSS是生成的html的样式,可以手动设置,使用此参数可以灵活的设置边距字体等信息)

package cn.qlq.docx4j;

import java.io.File;
import java.io.FileOutputStream;

import org.docx4j.Docx4J;
import org.docx4j.Docx4jProperties;
import org.docx4j.convert.out.HTMLSettings;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.samples.AbstractSample;

public class Docx2Html extends AbstractSample {

    public static void main(String[] args) throws Exception {
        String inputfilepath = "C:/Users/liqiang/Desktop/docx4j/helloworld.docx";
        boolean nestLists = true;

        WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage
                .load(new File("C:/Users/liqiang/Desktop/docx4j/helloworld.docx"));

        HTMLSettings htmlSettings = Docx4J.createHTMLSettings();

        htmlSettings.setImageDirPath(inputfilepath + "_files");
        htmlSettings.setImageTargetUri(inputfilepath.substring(inputfilepath.lastIndexOf("/") + 1) + "_files");
        htmlSettings.setWmlPackage(wordMLPackage);

        String userCSS = null;
        if (nestLists) {
            userCSS = "html, body, div, span, h1, h2, h3, h4, h5, h6, p, a, img,  table, caption, tbody, tfoot, thead, tr, th, td "
                    + "{ margin: 0; padding: 0; border: 0;}" + "body {line-height: 1;} ";
        } else {
            userCSS = "html, body, div, span, h1, h2, h3, h4, h5, h6, p, a, img,  ol, ul, li, table, caption, tbody, tfoot, thead, tr, th, td "
                    + "{ margin: 0; padding: 0; border: 0;}" + "body {line-height: 1;} ";

        }
        htmlSettings.setUserCSS(userCSS);

        Docx4jProperties.setProperty("docx4j.Convert.Out.HTML.OutputMethodXML", true);

        Docx4J.toHTML(htmlSettings, new FileOutputStream(new File("C:/Users/liqiang/Desktop/docx4j/helloworld.html")),
                Docx4J.FLAG_EXPORT_PREFER_XSL);

        if (wordMLPackage.getMainDocumentPart().getFontTablePart() != null) {
            wordMLPackage.getMainDocumentPart().getFontTablePart().deleteEmbeddedFontTempFiles();
        }
        htmlSettings = null;
        wordMLPackage = null;
    }
}

 

 

 2.docx转换为pdf

  代码简单,但是依赖的包比较多,依赖了batik解析SVG的项目包,也依赖fop包,而且docx4j-community-6.0.1.zip里面自带的optional\export-fo下面的fop-2.3.jar与docx冲突,所以需要fop-2.1版本才可以转换。所以需要删掉自带的2.3版本,自行下载2.1版本。

    public static void main(String[] args) throws Exception {
        WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage
                .load(new File("C:/Users/liqiang/Desktop/docx4j/helloworld.docx"));

        Docx4J.toPDF(wordMLPackage, new FileOutputStream(new File("C:/Users/liqiang/Desktop/docx4j/helloworld.pdf")));

    }

 

 

3.docx中写入图片 

package cn.qlq.docx4j;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;
import org.docx4j.wml.Drawing;
import org.docx4j.wml.ObjectFactory;
import org.docx4j.wml.P;
import org.docx4j.wml.R;

public class ImageHandle {
    /**
     * 像往常一样, 我们创建了一个包(package)来容纳文档. 然后我们创建了一个指向将要添加到文档的图片的文件对象.为了能够对图片做一些操作,
     * 我们将它转换 为字节数组. 最后我们将图片添加到包中并保存这个包(package).
     */
    public static void main(String[] args) throws Exception {
        WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
        File file = new File("C:/Users/liqiang/Desktop/docx4j/3.jpg");
        byte[] bytes = convertImageToByteArray(file);
        addImageToPackage(wordMLPackage, bytes);
        wordMLPackage.save(new java.io.File("C:/Users/liqiang/Desktop/docx4j/helloworld.docx"));
    }

    /**
     * Docx4j拥有一个由字节数组创建图片部件的工具方法, 随后将其添加到给定的包中. 为了能将图片添加 到一个段落中,
     * 我们需要将图片转换成内联对象. 这也有一个方法, 方法需要文件名提示, 替换文本, 两个id标识符和一个是嵌入还是链接到的指示作为参数.
     * 一个id用于文档中绘图对象不可见的属性, 另一个id用于图片本身不可见的绘制属性. 最后我们将内联 对象添加到段落中并将段落添加到包的主文档部件.
     *
     * @param wordMLPackage
     *            要添加图片的包
     * @param bytes
     *            图片对应的字节数组
     * @throws Exception
     *             不幸的createImageInline方法抛出一个异常(没有更多具体的异常类型)
     */
    private static void addImageToPackage(WordprocessingMLPackage wordMLPackage, byte[] bytes) throws Exception {
        BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wordMLPackage, bytes);

        int docPrId = 1;
        int cNvPrId = 2;
        org.docx4j.dml.wordprocessingDrawing.Inline inline = imagePart.createImageInline("Filename hint",
                "Alternative text", docPrId, cNvPrId, false);

        P paragraph = addInlineImageToParagraph(inline);

        wordMLPackage.getMainDocumentPart().addObject(paragraph);
    }

    /**
     * 创建一个对象工厂并用它创建一个段落和一个可运行块R. 然后将可运行块添加到段落中. 接下来创建一个图画并将其添加到可运行块R中. 最后我们将内联
     * 对象添加到图画中并返回段落对象.
     *
     * @param inline
     *            包含图片的内联对象.
     * @return 包含图片的段落
     */
    private static P addInlineImageToParagraph(org.docx4j.dml.wordprocessingDrawing.Inline inline) {
        // 添加内联对象到一个段落中
        ObjectFactory factory = new ObjectFactory();
        P paragraph = factory.createP();
        R run = factory.createR();
        paragraph.getContent().add(run);
        Drawing drawing = factory.createDrawing();
        run.getContent().add(drawing);
        drawing.getAnchorOrInline().add(inline);
        return paragraph;
    }

    /**
     * 将图片从文件对象转换成字节数组.
     * 
     * @param file
     *            将要转换的文件
     * @return 包含图片字节数据的字节数组
     * @throws FileNotFoundException
     * @throws IOException
     */
    private static byte[] convertImageToByteArray(File file) throws FileNotFoundException, IOException {
        InputStream is = new FileInputStream(file);
        long length = file.length();
        // 不能使用long类型创建数组, 需要用int类型.
        if (length > Integer.MAX_VALUE) {
            System.out.println("File too large!!");
        }
        byte[] bytes = new byte[(int) length];
        int offset = 0;
        int numRead = 0;
        while (offset < bytes.length && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
            offset += numRead;
        }
        // 确认所有的字节都没读取
        if (offset < bytes.length) {
            System.out.println("Could not completely read file " + file.getName());
        }
        is.close();
        return bytes;
    }
}

 

 

 4.按指定变量替换docx中的内容  ${var}替换

  注意:模板的${var}在书写的时候必须从左向右书写(不能直接{},然后在中间写括号),也就是转换成XML之后${var}必须是连续的,否则取不到变量。有时候取不到变量的时候可以抓换为xml然后查看你的变量是否是连续的。

    public static void main(String[] args) throws Exception {

        org.docx4j.wml.ObjectFactory foo = Context.getWmlObjectFactory();

        String template = "C:/Users/liqiang/Desktop/docx4j/helloworld.docx";

        boolean save = true;
        String outputfilepath = "C:/Users/liqiang/Desktop/docx4j/helloworld_1.docx";

        WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(new java.io.File(template));
        MainDocumentPart documentPart = wordMLPackage.getMainDocumentPart();

        //需要替换的map
        HashMap mappings = new HashMap();
        mappings.put("sex", "男");
        mappings.put("age", "25");
        mappings.put("username", "qlq");

        long start = System.currentTimeMillis();

        documentPart.variableReplace(mappings);

        long end = System.currentTimeMillis();
        long total = end - start;
        System.out.println("Time: " + total);

        // Save it
        if (save) {
            SaveToZipFile saver = new SaveToZipFile(wordMLPackage);
            saver.save(outputfilepath);
        } else {
            System.out.println(XmlUtils.marshaltoString(documentPart.getJaxbElement(), true, true));
        }
    }

 

模板:

【docx4j】docx4j操作docx,实现替换内容、转换pdf、html等操作_第6张图片

 

结果:

【docx4j】docx4j操作docx,实现替换内容、转换pdf、html等操作_第7张图片

 

补充:在docx进行变量替换的时候其格式也生效,比如我的模板:

【docx4j】docx4j操作docx,实现替换内容、转换pdf、html等操作_第8张图片

 

最后的结果:

【docx4j】docx4j操作docx,实现替换内容、转换pdf、html等操作_第9张图片

 

 5.替换模板里面的表格(循环替换标签)

 模板内容:

 

代码:

package cn.qlq.docx4j;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.bind.JAXBException;

import org.docx4j.Docx4J;
import org.docx4j.TraversalUtil;
import org.docx4j.XmlUtils;
import org.docx4j.finders.ClassFinder;
import org.docx4j.jaxb.Context;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import org.docx4j.wml.Tbl;
import org.docx4j.wml.Tr;

/**
 * 循环替换表格内容
 * 
 * @author QiaoLiQiang
 * @time 2018年10月28日下午8:51:41
 */
public class ReplaceTable {

    public static void main(String[] args) throws JAXBException {
        org.docx4j.wml.ObjectFactory objectFactory = Context.getWmlObjectFactory();

        String template = "C:/Users/liqiang/Desktop/docx4j/helloworld.docx";

        boolean save = true;
        String outputfilepath = "C:/Users/liqiang/Desktop/docx4j/helloworld_1.docx";

        WordprocessingMLPackage wordMLPackage;
        try {
            wordMLPackage = WordprocessingMLPackage.load(new java.io.File(template));
            MainDocumentPart documentPart = wordMLPackage.getMainDocumentPart();

            // 构造循环列表的数据
            ClassFinder find = new ClassFinder(Tbl.class);
            new TraversalUtil(wordMLPackage.getMainDocumentPart().getContent(), find);
            Tbl table = (Tbl) find.results.get(0);//获取到第一个表格元素
            Tr dynamicTr = (Tr) table.getContent().get(1);// 第二行约定为模板,获取到第二行内容
            String dynamicTrXml = XmlUtils.marshaltoString(dynamicTr);// 获取模板行的xml数据

            List> dataList = getDataList();
            for (Map dataMap : dataList) {
                Tr newTr = (Tr) XmlUtils.unmarshallFromTemplate(dynamicTrXml, dataMap);// 填充模板行数据
                table.getContent().add(newTr);
            }

            // 删除模板行的占位行
            table.getContent().remove(1);

            Docx4J.save(wordMLPackage, new File(outputfilepath));
        } catch (Docx4JException e) {
            e.printStackTrace();
        }
    }

    private static List> getDataList() {
        List list = new ArrayList();
        for (int i = 0; i < 5; i++) {
            Map map = new HashMap();
            map.put("name", "name" + i);
            map.put("sex", "sex" + i);
            map.put("age", "age" + i);
            list.add(map);
        }
        return list;
    }
}

结果:

【docx4j】docx4j操作docx,实现替换内容、转换pdf、html等操作_第10张图片

 

6.按书签替换内容(替换变量、表格、图片等格式数据)

   这种方式比基于变量的方式灵活,而且操作简单,我们只用在word中插入书签,如下:

【docx4j】docx4j操作docx,实现替换内容、转换pdf、html等操作_第11张图片

 

 代码:

package cn.qlq.docx4j;

import java.io.File;
import java.io.FileInputStream;
import java.util.List;

import org.apache.commons.io.IOUtils;
import org.docx4j.Docx4J;
import org.docx4j.TraversalUtil;
import org.docx4j.XmlUtils;
import org.docx4j.dml.wordprocessingDrawing.Inline;
import org.docx4j.finders.RangeFinder;
import org.docx4j.jaxb.Context;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import org.docx4j.wml.Body;
import org.docx4j.wml.CTBookmark;
import org.docx4j.wml.CTMarkupRange;
import org.docx4j.wml.ContentAccessor;
import org.docx4j.wml.Document;
import org.docx4j.wml.Drawing;
import org.docx4j.wml.ObjectFactory;
import org.docx4j.wml.P;
import org.docx4j.wml.PPr;
import org.docx4j.wml.ParaRPr;
import org.docx4j.wml.R;
import org.docx4j.wml.Text;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 通过书签替换变量
 * 
 * @author QiaoLiQiang
 * @time 2018年10月28日下午9:35:52
 */
public class BooknameReplaceVar {
    private static final Logger log = LoggerFactory.getLogger(BooknameReplaceVar.class);
    private static WordprocessingMLPackage wordMLPackage;
    private static ObjectFactory factory;

    public static void main(String[] args) {
        bookReplaceVarText();
    }

    private static void bookReplaceVarText() {
        String template = "C:/Users/liqiang/Desktop/docx4j/helloworld_1.docx";

        try {
            wordMLPackage = WordprocessingMLPackage.load(new java.io.File(template));
            MainDocumentPart mainDocumentPart = wordMLPackage.getMainDocumentPart();
            factory = Context.getWmlObjectFactory();

            Document wmlDoc = (Document) mainDocumentPart.getJaxbElement();
            Body body = wmlDoc.getBody();
            // 提取正文中所有段落
            List paragraphs = body.getContent();
            // 提取书签并创建书签的游标
            RangeFinder rt = new RangeFinder("CTBookmark", "CTMarkupRange");
            new TraversalUtil(paragraphs, rt);
            // 遍历书签
            for (CTBookmark bm : rt.getStarts()) {
                log.info("标签名称:" + bm.getName());
                // 这儿可以对单个书签进行操作,也可以用一个map对所有的书签进行处理
                if (bm.getName().equals("name")) {
                    replaceText(bm, "qlq");
                }
                if (bm.getName().equals("pic")) {
                    addImage(wordMLPackage, bm, "C:/Users/liqiang/Desktop/docx4j/3.jpg");
                }
            }
            Docx4J.save(wordMLPackage, new File("C:/Users/liqiang/Desktop/docx4j/helloworld_2.docx"));

        } catch (Docx4JException e) {
            log.error("bookReplaceVarText error:Docx4JException ", e);
        } catch (Exception e) {
            log.error("bookReplaceVarText error:Docx4JException ", e);
        }
    }

    /**
     * 在标签处插入内容
     * 
     * @param bm
     * @param wPackage
     * @param object
     * @throws Exception
     */
    public static void replaceText(CTBookmark bm, Object object) throws Exception {
        if (object == null) {
            return;
        }
        // do we have data for this one?
        if (bm.getName() == null)
            return;
        String value = object.toString();
        try {
            // Can't just remove the object from the parent,
            // since in the parent, it may be wrapped in a JAXBElement
            List theList = null;
            ParaRPr rpr = null;
            if (bm.getParent() instanceof P) {
                PPr pprTemp = ((P) (bm.getParent())).getPPr();
                if (pprTemp == null) {
                    rpr = null;
                } else {
                    rpr = ((P) (bm.getParent())).getPPr().getRPr();
                }
                theList = ((ContentAccessor) (bm.getParent())).getContent();
            } else {
                return;
            }
            int rangeStart = -1;
            int rangeEnd = -1;
            int i = 0;
            for (Object ox : theList) {
                Object listEntry = XmlUtils.unwrap(ox);
                if (listEntry.equals(bm)) {

                    if (((CTBookmark) listEntry).getName() != null) {

                        rangeStart = i + 1;

                    }
                } else if (listEntry instanceof CTMarkupRange) {
                    if (((CTMarkupRange) listEntry).getId().equals(bm.getId())) {
                        rangeEnd = i - 1;

                        break;
                    }
                }
                i++;
            }
            int x = i - 1;
            // if (rangeStart > 0 && x >= rangeStart) {
            // Delete the bookmark range
            for (int j = x; j >= rangeStart; j--) {
                theList.remove(j);
            }
            // now add a run
            org.docx4j.wml.R run = factory.createR();
            org.docx4j.wml.Text t = factory.createText();
            // if (rpr != null)
            // run.setRPr(paraRPr2RPr(rpr));
            t.setValue(value);
            run.getContent().add(t);
            // t.setValue(value);

            theList.add(rangeStart, run);
            // }
        } catch (ClassCastException cce) {
            log.error("error", cce);
        }
    }

    /**
     * 插入图片
     * 
     * @param wPackage
     * @param bm
     * @param file
     */
    public static void addImage(WordprocessingMLPackage wPackage, CTBookmark bm, String file) {
        log.info("addImage :->{},{},{}", wPackage, bm,file);
        try {
            // 这儿可以对单个书签进行操作,也可以用一个map对所有的书签进行处理
            // 获取该书签的父级段落
            P p = (P) (bm.getParent());
            // R对象是匿名的复杂类型,然而我并不知道具体啥意思,估计这个要好好去看看ooxml才知道
            R run = factory.createR();
            // 读入图片并转化为字节数组,因为docx4j只能字节数组的方式插入图片
            byte[] bytes = IOUtils.toByteArray(new FileInputStream(file));

            // InputStream is = new FileInputStream;
            // byte[] bytes = IOUtils.toByteArray(inputStream);
            // byte[] bytes = FileUtil.getByteFormBase64DataByImage("");
            // 开始创建一个行内图片
            BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wPackage, bytes);
            // createImageInline函数的前四个参数我都没有找到具体啥意思,,,,
            // 最有一个是限制图片的宽度,缩放的依据
            Inline inline = imagePart.createImageInline(null, null, 0, 1, false, 0);
            // 获取该书签的父级段落
            // drawing理解为画布?
            Drawing drawing = factory.createDrawing();
            drawing.getAnchorOrInline().add(inline);
            run.getContent().add(drawing);
            p.getContent().add(run);
        } catch (Exception e) {
            log.error("", e);
        }
    }
} 
    
   

 

 结果:上面的文本内容可以被完美的替换掉。如果在一般项目中进行替换书签为字符串变量已经足够了,替换图片还是有点格式问题。接下来还会继续研究书签的使用,尝试更简便的方式替换内容。

 

 

参考:https://github.com/plutext/docx4j/blob/master/src/samples

jar包下载地址:http://qiaoliqiang.cn/fileDown/docx4j-6.0.1-all.zip

 

 

补充:网上一位大哥写的工具类,比较实用:

测试代码;

    /**
     * 增加一个表格
     */
    public static void addTable() {
        try {
            WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
            ObjectFactory factory = Context.getWmlObjectFactory();
            MainDocumentPart mainDocumentPart = wordMLPackage.getMainDocumentPart();

            // 0. 创建表格元素
            Tbl table = factory.createTbl();

            // 1.显示表格的边框
            addBorders(table);

            // 2.添加表格内容(创建行和列)
            for (int i = 0; i < 3; i++) {
                Tr tr = factory.createTr();
                for (int j = 0; j < 3; j++) {
                    Tc tc = factory.createTc();

                    // P p = mainDocumentPart.createParagraphOfText("---row" + i
                    // + "---column" + j + "---");
                    // 第二种创建P并设置样式的方法
                    P p1 = factory.createP();
                    R r = factory.createR();
                    Text text = factory.createText();
                    text.setValue("---row" + i + "---column" + j + "---");

                    r.getContent().add(text);
                    p1.getContent().add(r);

                    // 2.1通过R设置字体加粗等属性
                    setRStyle(r);
                    // 2.2设置列宽
                    if (j == 1) {
                        setCellWidth(tc, 1250);
                    } else {
                        setCellWidth(tc, 2500);
                    }

                    tc.getContent().add(p1);
                    tr.getContent().add(tc);

                }
                table.getContent().add(tr);
            }

            // 3.合并单元格
            Docx4jUtil.mergeCellsHorizontal(table, 1, 0, 2);

            // 3.加表格加到主要内容中
            mainDocumentPart.addObject(table);
            wordMLPackage.save(new java.io.File("C:/Users/liqiang/Desktop/docx4j/helloworld.docx"));
        } catch (Docx4JException e) {
            log.error("createDocx error: Docx4JException", e);
        }
    }

    /**
     * 设置列宽
     * 
     * @param tc
     * @param width
     */
    private static void setCellWidth(Tc tc, int width) {
        TcPr tableCellProperties = new TcPr();
        TblWidth tableWidth = new TblWidth();
        tableWidth.setW(BigInteger.valueOf(width));
        tableCellProperties.setTcW(tableWidth);

        tc.setTcPr(tableCellProperties);
    }

    /**
     * 通过设置R设置表格中属性字体加粗,大小为25
     * 
     * @param
     */
    private static void setRStyle(R r) {
        // 1.创建一个RPr
        RPr rpr = new RPr();

        // 2.设置RPr
        // 2.1设置字体大小
        HpsMeasure size = new HpsMeasure();
        size.setVal(new BigInteger("25"));
        rpr.setSz(size);
        // 2.2设置加粗
        BooleanDefaultTrue bold = new BooleanDefaultTrue();
        bold.setVal(true);
        rpr.setB(bold);

        // 3.将RPr设置为R的属性
        r.setRPr(rpr);
    }

    /**
     * 设置边框样式
     * 
     * @param table
     *            需要设置表格边框的单元格
     */
    private static void addBorders(Tbl table) {
        table.setTblPr(new TblPr());// 必须设置一个TblPr,否则最后会报空指针异常

        CTBorder border = new CTBorder();
        border.setColor("auto");
        border.setSz(new BigInteger("4"));
        border.setSpace(new BigInteger("0"));
        border.setVal(STBorder.SINGLE);

        TblBorders borders = new TblBorders();
        borders.setBottom(border);
        borders.setLeft(border);
        borders.setRight(border);
        borders.setTop(border);
        borders.setInsideH(border);
        borders.setInsideV(border);

        // 获取其内部的TblPr属性设置属性
        table.getTblPr().setTblBorders(borders);
    }

 

结果:

【docx4j】docx4j操作docx,实现替换内容、转换pdf、html等操作_第12张图片

 

 

工具栏:

package cn.qlq.docx4j;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.StringWriter;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.JAXBElement;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.docx4j.TextUtils;
import org.docx4j.XmlUtils;
import org.docx4j.dml.wordprocessingDrawing.Inline;
import org.docx4j.model.properties.table.tr.TrHeight;
import org.docx4j.openpackaging.packages.OpcPackage;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import org.docx4j.openpackaging.parts.relationships.Namespaces;
import org.docx4j.wml.BooleanDefaultTrue;
import org.docx4j.wml.Br;
import org.docx4j.wml.CTBackground;
import org.docx4j.wml.CTBorder;
import org.docx4j.wml.CTEm;
import org.docx4j.wml.CTHeight;
import org.docx4j.wml.CTLineNumber;
import org.docx4j.wml.CTShd;
import org.docx4j.wml.CTSignedHpsMeasure;
import org.docx4j.wml.CTSignedTwipsMeasure;
import org.docx4j.wml.CTTblCellMar;
import org.docx4j.wml.CTTextScale;
import org.docx4j.wml.CTVerticalAlignRun;
import org.docx4j.wml.CTVerticalJc;
import org.docx4j.wml.Color;
import org.docx4j.wml.ContentAccessor;
import org.docx4j.wml.Drawing;
import org.docx4j.wml.Highlight;
import org.docx4j.wml.HpsMeasure;
import org.docx4j.wml.Jc;
import org.docx4j.wml.JcEnumeration;
import org.docx4j.wml.ObjectFactory;
import org.docx4j.wml.P;
import org.docx4j.wml.P.Hyperlink;
import org.docx4j.wml.PPr;
import org.docx4j.wml.PPrBase.Ind;
import org.docx4j.wml.PPrBase.PBdr;
import org.docx4j.wml.PPrBase.Spacing;
import org.docx4j.wml.ParaRPr;
import org.docx4j.wml.R;
import org.docx4j.wml.RFonts;
import org.docx4j.wml.RPr;
import org.docx4j.wml.STBorder;
import org.docx4j.wml.STBrType;
import org.docx4j.wml.STEm;
import org.docx4j.wml.STLineNumberRestart;
import org.docx4j.wml.STLineSpacingRule;
import org.docx4j.wml.STPageOrientation;
import org.docx4j.wml.STShd;
import org.docx4j.wml.STVerticalAlignRun;
import org.docx4j.wml.STVerticalJc;
import org.docx4j.wml.SectPr;
import org.docx4j.wml.SectPr.PgBorders;
import org.docx4j.wml.SectPr.PgMar;
import org.docx4j.wml.SectPr.PgSz;
import org.docx4j.wml.SectPr.Type;
import org.docx4j.wml.Tbl;
import org.docx4j.wml.TblBorders;
import org.docx4j.wml.TblGrid;
import org.docx4j.wml.TblGridCol;
import org.docx4j.wml.TblPr;
import org.docx4j.wml.TblWidth;
import org.docx4j.wml.Tc;
import org.docx4j.wml.TcPr;
import org.docx4j.wml.TcPrInner.GridSpan;
import org.docx4j.wml.TcPrInner.HMerge;
import org.docx4j.wml.TcPrInner.VMerge;
import org.docx4j.wml.Text;
import org.docx4j.wml.TextDirection;
import org.docx4j.wml.Tr;
import org.docx4j.wml.TrPr;
import org.docx4j.wml.U;
import org.docx4j.wml.UnderlineEnumeration;

public class Docx4jUtil {

    /*------------------------------------other---------------------------------------------------  */
    /**
     * @Description:新增超链接
     */
    public static void createHyperlink(WordprocessingMLPackage wordMLPackage, MainDocumentPart mainPart,
            ObjectFactory factory, P paragraph, String url, String value, String cnFontName, String enFontName,
            String fontSize) throws Exception {
        if (StringUtils.isBlank(enFontName)) {
            enFontName = "Times New Roman";
        }
        if (StringUtils.isBlank(cnFontName)) {
            cnFontName = "微软雅黑";
        }
        if (StringUtils.isBlank(fontSize)) {
            fontSize = "22";
        }
        org.docx4j.relationships.ObjectFactory reFactory = new org.docx4j.relationships.ObjectFactory();
        org.docx4j.relationships.Relationship rel = reFactory.createRelationship();
        rel.setType(Namespaces.HYPERLINK);
        rel.setTarget(url);
        rel.setTargetMode("External");
        mainPart.getRelationshipsPart().addRelationship(rel);
        StringBuffer sb = new StringBuffer();
        // addRelationship sets the rel's @Id
        sb.append(");
        sb.append(rel.getId());
        sb.append("\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" ");
        sb.append("xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" >");
        sb.append("");
        sb.append(");
        sb.append(enFontName);
        sb.append("\"  w:hAnsi=\"");
        sb.append(enFontName);
        sb.append("\"  w:eastAsia=\"");
        sb.append(cnFontName);
        sb.append("\" w:hint=\"eastAsia\"/>");
        sb.append(");
        sb.append(fontSize);
        sb.append("\"/>);
        sb.append(fontSize);
        sb.append("\"/>");
        sb.append(value);
        sb.append("");

        Hyperlink link = (Hyperlink) XmlUtils.unmarshalString(sb.toString());
        paragraph.getContent().add(link);
    }

    public static String getElementContent(Object obj) throws Exception {
        StringWriter stringWriter = new StringWriter();
        TextUtils.extractText(obj, stringWriter);
        return stringWriter.toString();
    }

    /**
     * @Description:得到指定类型的元素
     */
    public static List getAllElementFromObject(Object obj, Class toSearch) {
        List result = new ArrayList();
        if (obj instanceof JAXBElement)
            obj = ((JAXBElement) obj).getValue();
        if (obj.getClass().equals(toSearch))
            result.add(obj);
        else if (obj instanceof ContentAccessor) {
            List children = ((ContentAccessor) obj).getContent();
            for (Object child : children) {
                result.addAll(getAllElementFromObject(child, toSearch));
            }
        }
        return result;
    }

    /**
     * @Description:保存WordprocessingMLPackage
     */
    public static void saveWordPackage(WordprocessingMLPackage wordPackage, File file) throws Exception {
        wordPackage.save(file);
    }

    /**
     * @Description:新建WordprocessingMLPackage
     */
    public static WordprocessingMLPackage createWordprocessingMLPackage() throws Exception {
        return WordprocessingMLPackage.createPackage();
    }

    /**
     * @Description:加载带密码WordprocessingMLPackage
     */
    public static WordprocessingMLPackage loadWordprocessingMLPackageWithPwd(String filePath, String password)
            throws Exception {
        OpcPackage opcPackage = WordprocessingMLPackage.load(new java.io.File(filePath), password);
        WordprocessingMLPackage wordMLPackage = (WordprocessingMLPackage) opcPackage;
        return wordMLPackage;
    }

    /**
     * @Description:加载WordprocessingMLPackage
     */
    public static WordprocessingMLPackage loadWordprocessingMLPackage(String filePath) throws Exception {
        WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(new java.io.File(filePath));
        return wordMLPackage;
    }

    /*------------------------------------Word 表格相关---------------------------------------------------  */
    /**
     * @Description: 跨列合并
     */
    public static void mergeCellsHorizontalByGridSpan(Tbl tbl, int row, int fromCell, int toCell) {
        if (row < 0 || fromCell < 0 || toCell < 0) {
            return;
        }
        List trList = getTblAllTr(tbl);
        if (row > trList.size()) {
            return;
        }
        Tr tr = trList.get(row);
        List tcList = getTrAllCell(tr);
        for (int cellIndex = Math.min(tcList.size() - 1, toCell); cellIndex >= fromCell; cellIndex--) {
            Tc tc = tcList.get(cellIndex);
            TcPr tcPr = getTcPr(tc);
            if (cellIndex == fromCell) {
                GridSpan gridSpan = tcPr.getGridSpan();
                if (gridSpan == null) {
                    gridSpan = new GridSpan();
                    tcPr.setGridSpan(gridSpan);
                }
                gridSpan.setVal(BigInteger.valueOf(Math.min(tcList.size() - 1, toCell) - fromCell + 1));
            } else {
                tr.getContent().remove(cellIndex);
            }
        }
    }

    /**
     * @Description: 跨列合并
     */
    public static void mergeCellsHorizontal(Tbl tbl, int row, int fromCell, int toCell) {
        if (row < 0 || fromCell < 0 || toCell < 0) {
            return;
        }
        List trList = getTblAllTr(tbl);
        if (row > trList.size()) {
            return;
        }
        Tr tr = trList.get(row);
        List tcList = getTrAllCell(tr);
        for (int cellIndex = fromCell, len = Math.min(tcList.size() - 1, toCell); cellIndex <= len; cellIndex++) {
            Tc tc = tcList.get(cellIndex);
            TcPr tcPr = getTcPr(tc);
            HMerge hMerge = tcPr.getHMerge();
            if (hMerge == null) {
                hMerge = new HMerge();
                tcPr.setHMerge(hMerge);
            }
            if (cellIndex == fromCell) {
                hMerge.setVal("restart");
            } else {
                hMerge.setVal("continue");
            }
        }
    }

    /**
     * @Description: 跨行合并
     */
    public static void mergeCellsVertically(Tbl tbl, int col, int fromRow, int toRow) {
        if (col < 0 || fromRow < 0 || toRow < 0) {
            return;
        }
        for (int rowIndex = fromRow; rowIndex <= toRow; rowIndex++) {
            Tc tc = getTc(tbl, rowIndex, col);
            if (tc == null) {
                break;
            }
            TcPr tcPr = getTcPr(tc);
            VMerge vMerge = tcPr.getVMerge();
            if (vMerge == null) {
                vMerge = new VMerge();
                tcPr.setVMerge(vMerge);
            }
            if (rowIndex == fromRow) {
                vMerge.setVal("restart");
            } else {
                vMerge.setVal("continue");
            }
        }
    }

    /**
     * @Description:得到指定位置的单元格
     */
    public static Tc getTc(Tbl tbl, int row, int cell) {
        if (row < 0 || cell < 0) {
            return null;
        }
        List trList = getTblAllTr(tbl);
        if (row >= trList.size()) {
            return null;
        }
        List tcList = getTrAllCell(trList.get(row));
        if (cell >= tcList.size()) {
            return null;
        }
        return tcList.get(cell);
    }

    /**
     * @Description:得到所有表格
     */
    public static List getAllTbl(WordprocessingMLPackage wordMLPackage) {
        MainDocumentPart mainDocPart = wordMLPackage.getMainDocumentPart();
        List objList = getAllElementFromObject(mainDocPart, Tbl.class);
        if (objList == null) {
            return null;
        }
        List tblList = new ArrayList();
        for (Object obj : objList) {
            if (obj instanceof Tbl) {
                Tbl tbl = (Tbl) obj;
                tblList.add(tbl);
            }
        }
        return tblList;
    }

    /**
     * @Description:删除指定位置的表格,删除后表格数量减一
     */
    public static boolean removeTableByIndex(WordprocessingMLPackage wordMLPackage, int index) throws Exception {
        boolean flag = false;
        if (index < 0) {
            return flag;
        }
        List objList = wordMLPackage.getMainDocumentPart().getContent();
        if (objList == null) {
            return flag;
        }
        int k = -1;
        for (int i = 0, len = objList.size(); i < len; i++) {
            Object obj = XmlUtils.unwrap(objList.get(i));
            if (obj instanceof Tbl) {
                k++;
                if (k == index) {
                    wordMLPackage.getMainDocumentPart().getContent().remove(i);
                    flag = true;
                    break;
                }
            }
        }
        return flag;
    }

    /**
     * @Description: 获取单元格内容,无分割符
     */
    public static String getTblContentStr(Tbl tbl) throws Exception {
        return getElementContent(tbl);
    }

    /**
     * @Description: 获取表格内容
     */
    public static List getTblContentList(Tbl tbl) throws Exception {
        List resultList = new ArrayList();
        List trList = getTblAllTr(tbl);
        for (Tr tr : trList) {
            StringBuffer sb = new StringBuffer();
            List tcList = getTrAllCell(tr);
            for (Tc tc : tcList) {
                sb.append(getElementContent(tc) + ",");
            }
            resultList.add(sb.toString());
        }
        return resultList;
    }

    public static TblPr getTblPr(Tbl tbl) {
        TblPr tblPr = tbl.getTblPr();
        if (tblPr == null) {
            tblPr = new TblPr();
            tbl.setTblPr(tblPr);
        }
        return tblPr;
    }

    /**
     * @Description: 设置表格总宽度
     */
    public static void setTableWidth(Tbl tbl, String width) {
        if (StringUtils.isNotBlank(width)) {
            TblPr tblPr = getTblPr(tbl);
            TblWidth tblW = tblPr.getTblW();
            if (tblW == null) {
                tblW = new TblWidth();
                tblPr.setTblW(tblW);
            }
            tblW.setW(new BigInteger(width));
            tblW.setType("dxa");
        }
    }

    /**
     * @Description:创建表格(默认水平居中,垂直居中)
     */
    public static Tbl createTable(WordprocessingMLPackage wordPackage, int rowNum, int colsNum) throws Exception {
        colsNum = Math.max(1, colsNum);
        rowNum = Math.max(1, rowNum);
        int widthTwips = getWritableWidth(wordPackage);
        int colWidth = widthTwips / colsNum;
        int[] widthArr = new int[colsNum];
        for (int i = 0; i < colsNum; i++) {
            widthArr[i] = colWidth;
        }
        return createTable(rowNum, colsNum, widthArr);
    }

    /**
     * @Description:创建表格(默认水平居中,垂直居中)
     */
    public static Tbl createTable(int rowNum, int colsNum, int[] widthArr) throws Exception {
        colsNum = Math.max(1, Math.min(colsNum, widthArr.length));
        rowNum = Math.max(1, rowNum);
        Tbl tbl = new Tbl();
        StringBuffer tblSb = new StringBuffer();
        tblSb.append("");
        tblSb.append("");
        tblSb.append("");
        // 上边框
        tblSb.append("");
        tblSb.append("");
        // 左边框
        tblSb.append("");
        // 下边框
        tblSb.append("");
        // 右边框
        tblSb.append("");
        tblSb.append("");
        tblSb.append("");
        tblSb.append("");
        tblSb.append("");
        TblPr tblPr = null;
        tblPr = (TblPr) XmlUtils.unmarshalString(tblSb.toString());
        Jc jc = new Jc();
        // 单元格居中对齐
        jc.setVal(JcEnumeration.CENTER);
        tblPr.setJc(jc);

        tbl.setTblPr(tblPr);

        // 设定各单元格宽度
        TblGrid tblGrid = new TblGrid();
        tbl.setTblGrid(tblGrid);
        for (int i = 0; i < colsNum; i++) {
            TblGridCol gridCol = new TblGridCol();
            gridCol.setW(BigInteger.valueOf(widthArr[i]));
            tblGrid.getGridCol().add(gridCol);
        }
        // 新增行
        for (int j = 0; j < rowNum; j++) {
            Tr tr = new Tr();
            tbl.getContent().add(tr);
            //
            for (int i = 0; i < colsNum; i++) {
                Tc tc = new Tc();
                tr.getContent().add(tc);

                TcPr tcPr = new TcPr();
                TblWidth cellWidth = new TblWidth();
                cellWidth.setType("dxa");
                cellWidth.setW(BigInteger.valueOf(widthArr[i]));
                tcPr.setTcW(cellWidth);
                tc.setTcPr(tcPr);

                // 垂直居中
                setTcVAlign(tc, STVerticalJc.CENTER);
                P p = new P();
                PPr pPr = new PPr();
                pPr.setJc(jc);
                p.setPPr(pPr);
                R run = new R();
                p.getContent().add(run);
                tc.getContent().add(p);
            }
        }
        return tbl;
    }

    /**
     * @Description:表格增加边框 可以设置上下左右四个边框样式以及横竖水平线样式
     */
    public static void setTblBorders(TblPr tblPr, CTBorder topBorder, CTBorder rightBorder, CTBorder bottomBorder,
            CTBorder leftBorder, CTBorder hBorder, CTBorder vBorder) {
        TblBorders borders = tblPr.getTblBorders();
        if (borders == null) {
            borders = new TblBorders();
            tblPr.setTblBorders(borders);
        }
        if (topBorder != null) {
            borders.setTop(topBorder);
        }
        if (rightBorder != null) {
            borders.setRight(rightBorder);
        }
        if (bottomBorder != null) {
            borders.setBottom(bottomBorder);
        }
        if (leftBorder != null) {
            borders.setLeft(leftBorder);
        }
        if (hBorder != null) {
            borders.setInsideH(hBorder);
        }
        if (vBorder != null) {
            borders.setInsideV(vBorder);
        }
    }

    /**
     * @Description: 设置表格水平对齐方式(仅对表格起作用,单元格不一定水平对齐)
     */
    public static void setTblJcAlign(Tbl tbl, JcEnumeration jcType) {
        if (jcType != null) {
            TblPr tblPr = getTblPr(tbl);
            Jc jc = tblPr.getJc();
            if (jc == null) {
                jc = new Jc();
                tblPr.setJc(jc);
            }
            jc.setVal(jcType);
        }
    }

    /**
     * @Description: 设置表格水平对齐方式(包括单元格),只对该方法前面产生的单元格起作用
     */
    public static void setTblAllJcAlign(Tbl tbl, JcEnumeration jcType) {
        if (jcType != null) {
            setTblJcAlign(tbl, jcType);
            List trList = getTblAllTr(tbl);
            for (Tr tr : trList) {
                List tcList = getTrAllCell(tr);
                for (Tc tc : tcList) {
                    setTcJcAlign(tc, jcType);
                }
            }
        }
    }

    /**
     * @Description: 设置表格垂直对齐方式(包括单元格),只对该方法前面产生的单元格起作用
     */
    public static void setTblAllVAlign(Tbl tbl, STVerticalJc vAlignType) {
        if (vAlignType != null) {
            List trList = getTblAllTr(tbl);
            for (Tr tr : trList) {
                List tcList = getTrAllCell(tr);
                for (Tc tc : tcList) {
                    setTcVAlign(tc, vAlignType);
                }
            }
        }
    }

    /**
     * @Description: 设置单元格Margin
     */
    public static void setTableCellMargin(Tbl tbl, String top, String right, String bottom, String left) {
        TblPr tblPr = getTblPr(tbl);
        CTTblCellMar cellMar = tblPr.getTblCellMar();
        if (cellMar == null) {
            cellMar = new CTTblCellMar();
            tblPr.setTblCellMar(cellMar);
        }
        if (StringUtils.isNotBlank(top)) {
            TblWidth topW = new TblWidth();
            topW.setW(new BigInteger(top));
            topW.setType("dxa");
            cellMar.setTop(topW);
        }
        if (StringUtils.isNotBlank(right)) {
            TblWidth rightW = new TblWidth();
            rightW.setW(new BigInteger(right));
            rightW.setType("dxa");
            cellMar.setRight(rightW);
        }
        if (StringUtils.isNotBlank(bottom)) {
            TblWidth btW = new TblWidth();
            btW.setW(new BigInteger(bottom));
            btW.setType("dxa");
            cellMar.setBottom(btW);
        }
        if (StringUtils.isNotBlank(left)) {
            TblWidth leftW = new TblWidth();
            leftW.setW(new BigInteger(left));
            leftW.setType("dxa");
            cellMar.setLeft(leftW);
        }
    }

    /**
     * @Description: 得到表格所有的行
     */
    public static List getTblAllTr(Tbl tbl) {
        List objList = getAllElementFromObject(tbl, Tr.class);
        List trList = new ArrayList();
        if (objList == null) {
            return trList;
        }
        for (Object obj : objList) {
            if (obj instanceof Tr) {
                Tr tr = (Tr) obj;
                trList.add(tr);
            }
        }
        return trList;

    }

    /**
     * @Description:设置tr高度
     */
    public static void setTrHeight(Tr tr, String heigth) {
        TrPr trPr = getTrPr(tr);
        CTHeight ctHeight = new CTHeight();
        ctHeight.setVal(new BigInteger(heigth));
        TrHeight trHeight = new TrHeight(ctHeight);
        trHeight.set(trPr);
    }

    /**
     * @Description: 在表格指定位置新增一行,默认居中
     */
    public static void addTrByIndex(Tbl tbl, int index) {
        addTrByIndex(tbl, index, STVerticalJc.CENTER, JcEnumeration.CENTER);
    }

    /**
     * @Description: 在表格指定位置新增一行(默认按表格定义的列数添加)
     */
    public static void addTrByIndex(Tbl tbl, int index, STVerticalJc vAlign, JcEnumeration hAlign) {
        TblGrid tblGrid = tbl.getTblGrid();
        Tr tr = new Tr();
        if (tblGrid != null) {
            List gridList = tblGrid.getGridCol();
            for (TblGridCol tblGridCol : gridList) {
                Tc tc = new Tc();
                setTcWidth(tc, tblGridCol.getW().toString());
                if (vAlign != null) {
                    // 垂直居中
                    setTcVAlign(tc, vAlign);
                }
                P p = new P();
                if (hAlign != null) {
                    PPr pPr = new PPr();
                    Jc jc = new Jc();
                    // 单元格居中对齐
                    jc.setVal(hAlign);
                    pPr.setJc(jc);
                    p.setPPr(pPr);
                }
                R run = new R();
                p.getContent().add(run);
                tc.getContent().add(p);
                tr.getContent().add(tc);
            }
        } else {
            // 大部分情况都不会走到这一步
            Tr firstTr = getTblAllTr(tbl).get(0);
            int cellSize = getTcCellSizeWithMergeNum(firstTr);
            for (int i = 0; i < cellSize; i++) {
                Tc tc = new Tc();
                if (vAlign != null) {
                    // 垂直居中
                    setTcVAlign(tc, vAlign);
                }
                P p = new P();
                if (hAlign != null) {
                    PPr pPr = new PPr();
                    Jc jc = new Jc();
                    // 单元格居中对齐
                    jc.setVal(hAlign);
                    pPr.setJc(jc);
                    p.setPPr(pPr);
                }
                R run = new R();
                p.getContent().add(run);
                tc.getContent().add(p);
                tr.getContent().add(tc);
            }
        }
        if (index >= 0 && index < tbl.getContent().size()) {
            tbl.getContent().add(index, tr);
        } else {
            tbl.getContent().add(tr);
        }
    }

    /**
     * @Description: 得到行的列数
     */
    public static int getTcCellSizeWithMergeNum(Tr tr) {
        int cellSize = 1;
        List tcList = getTrAllCell(tr);
        if (tcList == null || tcList.size() == 0) {
            return cellSize;
        }
        cellSize = tcList.size();
        for (Tc tc : tcList) {
            TcPr tcPr = getTcPr(tc);
            GridSpan gridSpan = tcPr.getGridSpan();
            if (gridSpan != null) {
                cellSize += gridSpan.getVal().intValue() - 1;
            }
        }
        return cellSize;
    }

    /**
     * @Description: 删除指定行 删除后行数减一
     */
    public static boolean removeTrByIndex(Tbl tbl, int index) {
        boolean flag = false;
        if (index < 0) {
            return flag;
        }
        List objList = tbl.getContent();
        if (objList == null) {
            return flag;
        }
        int k = -1;
        for (int i = 0, len = objList.size(); i < len; i++) {
            Object obj = XmlUtils.unwrap(objList.get(i));
            if (obj instanceof Tr) {
                k++;
                if (k == index) {
                    tbl.getContent().remove(i);
                    flag = true;
                    break;
                }
            }
        }
        return flag;
    }

    public static TrPr getTrPr(Tr tr) {
        TrPr trPr = tr.getTrPr();
        if (trPr == null) {
            trPr = new TrPr();
            tr.setTrPr(trPr);
        }
        return trPr;
    }

    /**
     * @Description:隐藏行(只对表格中间的部分起作用,不包括首尾行)
     */
    public static void setTrHidden(Tr tr, boolean hidden) {
        List tcList = getTrAllCell(tr);
        for (Tc tc : tcList) {
            setTcHidden(tc, hidden);
        }
    }

    /**
     * @Description: 设置单元格宽度
     */
    public static void setTcWidth(Tc tc, String width) {
        if (StringUtils.isNotBlank(width)) {
            TcPr tcPr = getTcPr(tc);
            TblWidth tcW = tcPr.getTcW();
            if (tcW == null) {
                tcW = new TblWidth();
                tcPr.setTcW(tcW);
            }
            tcW.setW(new BigInteger(width));
            tcW.setType("dxa");
        }
    }

    /**
     * @Description: 隐藏单元格内容
     */
    public static void setTcHidden(Tc tc, boolean hidden) {
        List

pList = getTcAllP(tc); for (P p : pList) { PPr ppr = getPPr(p); List objRList = getAllElementFromObject(p, R.class); if (objRList == null) { continue; } for (Object objR : objRList) { if (objR instanceof R) { R r = (R) objR; RPr rpr = getRPr(r); setRPrVanishStyle(rpr, hidden); } } setParaVanish(ppr, hidden); } } public static List

getTcAllP(Tc tc) { List objList = getAllElementFromObject(tc, P.class); List

pList = new ArrayList

(); if (objList == null) { return pList; } for (Object obj : objList) { if (obj instanceof P) { P p = (P) obj; pList.add(p); } } return pList; } public static TcPr getTcPr(Tc tc) { TcPr tcPr = tc.getTcPr(); if (tcPr == null) { tcPr = new TcPr(); tc.setTcPr(tcPr); } return tcPr; } /** * @Description: 设置单元格垂直对齐方式 */ public static void setTcVAlign(Tc tc, STVerticalJc vAlignType) { if (vAlignType != null) { TcPr tcPr = getTcPr(tc); CTVerticalJc vAlign = new CTVerticalJc(); vAlign.setVal(vAlignType); tcPr.setVAlign(vAlign); } } /** * @Description: 设置单元格水平对齐方式 */ public static void setTcJcAlign(Tc tc, JcEnumeration jcType) { if (jcType != null) { List

pList = getTcAllP(tc); for (P p : pList) { setParaJcAlign(p, jcType); } } } public static RPr getRPr(R r) { RPr rpr = r.getRPr(); if (rpr == null) { rpr = new RPr(); r.setRPr(rpr); } return rpr; } /** * @Description: 获取所有的单元格 */ public static List getTrAllCell(Tr tr) { List objList = getAllElementFromObject(tr, Tc.class); List tcList = new ArrayList(); if (objList == null) { return tcList; } for (Object tcObj : objList) { if (tcObj instanceof Tc) { Tc objTc = (Tc) tcObj; tcList.add(objTc); } } return tcList; } /** * @Description: 获取单元格内容 */ public static String getTcContent(Tc tc) throws Exception { return getElementContent(tc); } /** * @Description:设置单元格内容,content为null则清除单元格内容 */ public static void setTcContent(Tc tc, RPr rpr, String content) { List pList = tc.getContent(); P p = null; if (pList != null && pList.size() > 0) { if (pList.get(0) instanceof P) { p = (P) pList.get(0); } } else { p = new P(); tc.getContent().add(p); } R run = null; List rList = p.getContent(); if (rList != null && rList.size() > 0) { for (int i = 0, len = rList.size(); i < len; i++) { // 清除内容(所有的r p.getContent().remove(0); } } run = new R(); p.getContent().add(run); if (content != null) { String[] contentArr = content.split("\n"); Text text = new Text(); text.setSpace("preserve"); text.setValue(contentArr[0]); run.setRPr(rpr); run.getContent().add(text); for (int i = 1, len = contentArr.length; i < len; i++) { Br br = new Br(); run.getContent().add(br);// 换行 text = new Text(); text.setSpace("preserve"); text.setValue(contentArr[i]); run.setRPr(rpr); run.getContent().add(text); } } } /** * @Description:设置单元格内容,content为null则清除单元格内容 */ public static void removeTcContent(Tc tc) { List pList = tc.getContent(); P p = null; if (pList != null && pList.size() > 0) { if (pList.get(0) instanceof P) { p = (P) pList.get(0); } } else { return; } List rList = p.getContent(); if (rList != null && rList.size() > 0) { for (int i = 0, len = rList.size(); i < len; i++) { // 清除内容(所有的r p.getContent().remove(0); } } } /** * @Description:删除指定位置的表格 * @deprecated */ public static void deleteTableByIndex2(WordprocessingMLPackage wordMLPackage, int index) throws Exception { if (index < 0) { return; } final String xpath = "(//w:tbl)[" + index + "]"; final List jaxbNodes = wordMLPackage.getMainDocumentPart().getJAXBNodesViaXPath(xpath, true); if (jaxbNodes != null && jaxbNodes.size() > 0) { wordMLPackage.getMainDocumentPart().getContent().remove(jaxbNodes.get(0)); } } /** * @Description:获取NodeList * @deprecated */ public static List getObjectByXpath(WordprocessingMLPackage wordMLPackage, String xpath) throws Exception { final List jaxbNodes = wordMLPackage.getMainDocumentPart().getJAXBNodesViaXPath(xpath, true); return jaxbNodes; } /*------------------------------------Word 段落相关--------------------------------------------------- */ /** * @Description: 只删除单独的段落,不包括表格内或其他内的段落 */ public static boolean removeParaByIndex(WordprocessingMLPackage wordMLPackage, int index) { boolean flag = false; if (index < 0) { return flag; } List objList = wordMLPackage.getMainDocumentPart().getContent(); if (objList == null) { return flag; } int k = -1; for (int i = 0, len = objList.size(); i < len; i++) { if (objList.get(i) instanceof P) { k++; if (k == index) { wordMLPackage.getMainDocumentPart().getContent().remove(i); flag = true; break; } } } return flag; } /** * @Description: 设置段落水平对齐方式 */ public static void setParaJcAlign(P paragraph, JcEnumeration hAlign) { if (hAlign != null) { PPr pprop = paragraph.getPPr(); if (pprop == null) { pprop = new PPr(); paragraph.setPPr(pprop); } Jc align = new Jc(); align.setVal(hAlign); pprop.setJc(align); } } /** * @Description: 设置段落内容 */ public static void setParaRContent(P p, RPr runProperties, String content) { R run = null; List rList = p.getContent(); if (rList != null && rList.size() > 0) { for (int i = 0, len = rList.size(); i < len; i++) { // 清除内容(所有的r p.getContent().remove(0); } } run = new R(); p.getContent().add(run); if (content != null) { String[] contentArr = content.split("\n"); Text text = new Text(); text.setSpace("preserve"); text.setValue(contentArr[0]); run.setRPr(runProperties); run.getContent().add(text); for (int i = 1, len = contentArr.length; i < len; i++) { Br br = new Br(); run.getContent().add(br);// 换行 text = new Text(); text.setSpace("preserve"); text.setValue(contentArr[i]); run.setRPr(runProperties); run.getContent().add(text); } } } /** * @Description: 添加段落内容 */ public static void appendParaRContent(P p, RPr runProperties, String content) { if (content != null) { R run = new R(); p.getContent().add(run); String[] contentArr = content.split("\n"); Text text = new Text(); text.setSpace("preserve"); text.setValue(contentArr[0]); run.setRPr(runProperties); run.getContent().add(text); for (int i = 1, len = contentArr.length; i < len; i++) { Br br = new Br(); run.getContent().add(br);// 换行 text = new Text(); text.setSpace("preserve"); text.setValue(contentArr[i]); run.setRPr(runProperties); run.getContent().add(text); } } } /** * @Description: 添加图片到段落 */ public static void addImageToPara(WordprocessingMLPackage wordMLPackage, ObjectFactory factory, P paragraph, String filePath, String content, RPr rpr, String altText, int id1, int id2) throws Exception { R run = factory.createR(); if (content != null) { Text text = factory.createText(); text.setValue(content); text.setSpace("preserve"); run.setRPr(rpr); run.getContent().add(text); } InputStream is = new FileInputStream(filePath); byte[] bytes = IOUtils.toByteArray(is); BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wordMLPackage, bytes); Inline inline = imagePart.createImageInline(filePath, altText, id1, id2, false); Drawing drawing = factory.createDrawing(); drawing.getAnchorOrInline().add(inline); run.getContent().add(drawing); paragraph.getContent().add(run); } /** * @Description: 段落添加Br 页面Break(分页符) */ public static void addPageBreak(P para, STBrType sTBrType) { Br breakObj = new Br(); breakObj.setType(sTBrType); para.getContent().add(breakObj); } /** * @Description: 设置段落是否禁止行号(禁止用于当前行号) */ public static void setParagraphSuppressLineNum(P p) { PPr ppr = getPPr(p); BooleanDefaultTrue line = ppr.getSuppressLineNumbers(); if (line == null) { line = new BooleanDefaultTrue(); } line.setVal(true); ppr.setSuppressLineNumbers(line); } /** * @Description: 设置段落底纹(对整段文字起作用) */ public static void setParagraphShdStyle(P p, STShd shdType, String shdColor) { PPr ppr = getPPr(p); CTShd ctShd = ppr.getShd(); if (ctShd == null) { ctShd = new CTShd(); } if (StringUtils.isNotBlank(shdColor)) { ctShd.setColor(shdColor); } if (shdType != null) { ctShd.setVal(shdType); } ppr.setShd(ctShd); } /** * @param isSpace * 是否设置段前段后值 * @param before * 段前磅数 * @param after * 段后磅数 * @param beforeLines * 段前行数 * @param afterLines * 段后行数 * @param isLine * 是否设置行距 * @param lineValue * 行距值 * @param sTLineSpacingRule * 自动auto 固定exact 最小 atLeast 1磅=20 1行=100 单倍行距=240 */ public static void setParagraphSpacing(P p, boolean isSpace, String before, String after, String beforeLines, String afterLines, boolean isLine, String lineValue, STLineSpacingRule sTLineSpacingRule) { PPr pPr = getPPr(p); Spacing spacing = pPr.getSpacing(); if (spacing == null) { spacing = new Spacing(); pPr.setSpacing(spacing); } if (isSpace) { if (StringUtils.isNotBlank(before)) { // 段前磅数 spacing.setBefore(new BigInteger(before)); } if (StringUtils.isNotBlank(after)) { // 段后磅数 spacing.setAfter(new BigInteger(after)); } if (StringUtils.isNotBlank(beforeLines)) { // 段前行数 spacing.setBeforeLines(new BigInteger(beforeLines)); } if (StringUtils.isNotBlank(afterLines)) { // 段后行数 spacing.setAfterLines(new BigInteger(afterLines)); } } if (isLine) { if (StringUtils.isNotBlank(lineValue)) { spacing.setLine(new BigInteger(lineValue)); } if (sTLineSpacingRule != null) { spacing.setLineRule(sTLineSpacingRule); } } } /** * @Description: 设置段落缩进信息 1厘米≈567 */ public static void setParagraphIndInfo(P p, String firstLine, String firstLineChar, String hanging, String hangingChar, String right, String rigthChar, String left, String leftChar) { PPr ppr = getPPr(p); Ind ind = ppr.getInd(); if (ind == null) { ind = new Ind(); ppr.setInd(ind); } if (StringUtils.isNotBlank(firstLine)) { ind.setFirstLine(new BigInteger(firstLine)); } if (StringUtils.isNotBlank(firstLineChar)) { ind.setFirstLineChars(new BigInteger(firstLineChar)); } if (StringUtils.isNotBlank(hanging)) { ind.setHanging(new BigInteger(hanging)); } if (StringUtils.isNotBlank(hangingChar)) { ind.setHangingChars(new BigInteger(hangingChar)); } if (StringUtils.isNotBlank(left)) { ind.setLeft(new BigInteger(left)); } if (StringUtils.isNotBlank(leftChar)) { ind.setLeftChars(new BigInteger(leftChar)); } if (StringUtils.isNotBlank(right)) { ind.setRight(new BigInteger(right)); } if (StringUtils.isNotBlank(rigthChar)) { ind.setRightChars(new BigInteger(rigthChar)); } } public static PPr getPPr(P p) { PPr ppr = p.getPPr(); if (ppr == null) { ppr = new PPr(); p.setPPr(ppr); } return ppr; } public static ParaRPr getParaRPr(PPr ppr) { ParaRPr parRpr = ppr.getRPr(); if (parRpr == null) { parRpr = new ParaRPr(); ppr.setRPr(parRpr); } return parRpr; } public static void setParaVanish(PPr ppr, boolean isVanish) { ParaRPr parRpr = getParaRPr(ppr); BooleanDefaultTrue vanish = parRpr.getVanish(); if (vanish != null) { vanish.setVal(isVanish); } else { vanish = new BooleanDefaultTrue(); parRpr.setVanish(vanish); vanish.setVal(isVanish); } } /** * @Description: 设置段落边框样式 */ public static void setParagraghBorders(P p, CTBorder topBorder, CTBorder bottomBorder, CTBorder leftBorder, CTBorder rightBorder) { PPr ppr = getPPr(p); PBdr pBdr = new PBdr(); if (topBorder != null) { pBdr.setTop(topBorder); } if (bottomBorder != null) { pBdr.setBottom(bottomBorder); } if (leftBorder != null) { pBdr.setLeft(leftBorder); } if (rightBorder != null) { pBdr.setRight(rightBorder); } ppr.setPBdr(pBdr); } /** * @Description: 设置字体信息 */ public static void setFontStyle(RPr runProperties, String cnFontFamily, String enFontFamily, String fontSize, String color) { setFontFamily(runProperties, cnFontFamily, enFontFamily); setFontSize(runProperties, fontSize); setFontColor(runProperties, color); } /** * @Description: 设置字体大小 */ public static void setFontSize(RPr runProperties, String fontSize) { if (StringUtils.isNotBlank(fontSize)) { HpsMeasure size = new HpsMeasure(); size.setVal(new BigInteger(fontSize)); runProperties.setSz(size); runProperties.setSzCs(size); } } /** * @Description: 设置字体 */ public static void setFontFamily(RPr runProperties, String cnFontFamily, String enFontFamily) { if (StringUtils.isNotBlank(cnFontFamily) || StringUtils.isNotBlank(enFontFamily)) { RFonts rf = runProperties.getRFonts(); if (rf == null) { rf = new RFonts(); runProperties.setRFonts(rf); } if (cnFontFamily != null) { rf.setEastAsia(cnFontFamily); } if (enFontFamily != null) { rf.setAscii(enFontFamily); } } } /** * @Description: 设置字体颜色 */ public static void setFontColor(RPr runProperties, String color) { if (color != null) { Color c = new Color(); c.setVal(color); runProperties.setColor(c); } } /** * @Description: 设置字符边框 */ public static void addRPrBorderStyle(RPr runProperties, String size, STBorder bordType, String space, String color) { CTBorder value = new CTBorder(); if (StringUtils.isNotBlank(color)) { value.setColor(color); } if (StringUtils.isNotBlank(size)) { value.setSz(new BigInteger(size)); } if (StringUtils.isNotBlank(space)) { value.setSpace(new BigInteger(space)); } if (bordType != null) { value.setVal(bordType); } runProperties.setBdr(value); } /** * @Description:着重号 */ public static void addRPrEmStyle(RPr runProperties, STEm emType) { if (emType != null) { CTEm em = new CTEm(); em.setVal(emType); runProperties.setEm(em); } } /** * @Description: 空心 */ public static void addRPrOutlineStyle(RPr runProperties) { BooleanDefaultTrue outline = new BooleanDefaultTrue(); outline.setVal(true); runProperties.setOutline(outline); } /** * @Description: 设置上标下标 */ public static void addRPrcaleStyle(RPr runProperties, STVerticalAlignRun vAlign) { if (vAlign != null) { CTVerticalAlignRun value = new CTVerticalAlignRun(); value.setVal(vAlign); runProperties.setVertAlign(value); } } /** * @Description: 设置字符间距缩进 */ public static void addRPrScaleStyle(RPr runProperties, int indent) { CTTextScale value = new CTTextScale(); value.setVal(indent); runProperties.setW(value); } /** * @Description: 设置字符间距信息 */ public static void addRPrtSpacingStyle(RPr runProperties, int spacing) { CTSignedTwipsMeasure value = new CTSignedTwipsMeasure(); value.setVal(BigInteger.valueOf(spacing)); runProperties.setSpacing(value); } /** * @Description: 设置文本位置 */ public static void addRPrtPositionStyle(RPr runProperties, int position) { CTSignedHpsMeasure ctPosition = new CTSignedHpsMeasure(); ctPosition.setVal(BigInteger.valueOf(position)); runProperties.setPosition(ctPosition); } /** * @Description: 阴文 */ public static void addRPrImprintStyle(RPr runProperties) { BooleanDefaultTrue imprint = new BooleanDefaultTrue(); imprint.setVal(true); runProperties.setImprint(imprint); } /** * @Description: 阳文 */ public static void addRPrEmbossStyle(RPr runProperties) { BooleanDefaultTrue emboss = new BooleanDefaultTrue(); emboss.setVal(true); runProperties.setEmboss(emboss); } /** * @Description: 设置隐藏 */ public static void setRPrVanishStyle(RPr runProperties, boolean isVanish) { BooleanDefaultTrue vanish = runProperties.getVanish(); if (vanish != null) { vanish.setVal(isVanish); } else { vanish = new BooleanDefaultTrue(); vanish.setVal(isVanish); runProperties.setVanish(vanish); } } /** * @Description: 设置阴影 */ public static void addRPrShadowStyle(RPr runProperties) { BooleanDefaultTrue shadow = new BooleanDefaultTrue(); shadow.setVal(true); runProperties.setShadow(shadow); } /** * @Description: 设置底纹 */ public static void addRPrShdStyle(RPr runProperties, STShd shdtype) { if (shdtype != null) { CTShd shd = new CTShd(); shd.setVal(shdtype); runProperties.setShd(shd); } } /** * @Description: 设置突出显示文本 */ public static void addRPrHightLightStyle(RPr runProperties, String hightlight) { if (StringUtils.isNotBlank(hightlight)) { Highlight highlight = new Highlight(); highlight.setVal(hightlight); runProperties.setHighlight(highlight); } } /** * @Description: 设置删除线样式 */ public static void addRPrStrikeStyle(RPr runProperties, boolean isStrike, boolean isDStrike) { // 删除线 if (isStrike) { BooleanDefaultTrue strike = new BooleanDefaultTrue(); strike.setVal(true); runProperties.setStrike(strike); } // 双删除线 if (isDStrike) { BooleanDefaultTrue dStrike = new BooleanDefaultTrue(); dStrike.setVal(true); runProperties.setDstrike(dStrike); } } /** * @Description: 加粗 */ public static void addRPrBoldStyle(RPr runProperties) { BooleanDefaultTrue b = new BooleanDefaultTrue(); b.setVal(true); runProperties.setB(b); } /** * @Description: 倾斜 */ public static void addRPrItalicStyle(RPr runProperties) { BooleanDefaultTrue b = new BooleanDefaultTrue(); b.setVal(true); runProperties.setI(b); } /** * @Description: 添加下划线 */ public static void addRPrUnderlineStyle(RPr runProperties, UnderlineEnumeration enumType) { U val = new U(); val.setVal(enumType); runProperties.setU(val); } /*------------------------------------Word 相关--------------------------------------------------- */ /** * @Description: 设置分节符 nextPage:下一页 continuous:连续 evenPage:偶数页 oddPage:奇数页 */ public static void setDocSectionBreak(WordprocessingMLPackage wordPackage, String sectValType) { if (StringUtils.isNotBlank(sectValType)) { SectPr sectPr = getDocSectPr(wordPackage); Type sectType = sectPr.getType(); if (sectType == null) { sectType = new Type(); sectPr.setType(sectType); } sectType.setVal(sectValType); } } /** * @Description: 设置页面背景色 */ public static void setDocumentBackGround(WordprocessingMLPackage wordPackage, ObjectFactory factory, String color) throws Exception { MainDocumentPart mdp = wordPackage.getMainDocumentPart(); CTBackground bkground = mdp.getContents().getBackground(); if (StringUtils.isNotBlank(color)) { if (bkground == null) { bkground = factory.createCTBackground(); bkground.setColor(color); } mdp.getContents().setBackground(bkground); } } /** * @Description: 设置页面边框 */ public static void setDocumentBorders(WordprocessingMLPackage wordPackage, ObjectFactory factory, CTBorder top, CTBorder right, CTBorder bottom, CTBorder left) { SectPr sectPr = getDocSectPr(wordPackage); PgBorders pgBorders = sectPr.getPgBorders(); if (pgBorders == null) { pgBorders = factory.createSectPrPgBorders(); sectPr.setPgBorders(pgBorders); } if (top != null) { pgBorders.setTop(top); } if (right != null) { pgBorders.setRight(right); } if (bottom != null) { pgBorders.setBottom(bottom); } if (left != null) { pgBorders.setLeft(left); } } /** * @Description: 设置页面大小及纸张方向 landscape横向 */ public static void setDocumentSize(WordprocessingMLPackage wordPackage, ObjectFactory factory, String width, String height, STPageOrientation stValue) { SectPr sectPr = getDocSectPr(wordPackage); PgSz pgSz = sectPr.getPgSz(); if (pgSz == null) { pgSz = factory.createSectPrPgSz(); sectPr.setPgSz(pgSz); } if (StringUtils.isNotBlank(width)) { pgSz.setW(new BigInteger(width)); } if (StringUtils.isNotBlank(height)) { pgSz.setH(new BigInteger(height)); } if (stValue != null) { pgSz.setOrient(stValue); } } public static SectPr getDocSectPr(WordprocessingMLPackage wordPackage) { SectPr sectPr = wordPackage.getDocumentModel().getSections().get(0).getSectPr(); return sectPr; } /** * @Description:设置页边距 */ public static void setDocMarginSpace(WordprocessingMLPackage wordPackage, ObjectFactory factory, String top, String left, String bottom, String right) { SectPr sectPr = getDocSectPr(wordPackage); PgMar pg = sectPr.getPgMar(); if (pg == null) { pg = factory.createSectPrPgMar(); sectPr.setPgMar(pg); } if (StringUtils.isNotBlank(top)) { pg.setTop(new BigInteger(top)); } if (StringUtils.isNotBlank(bottom)) { pg.setBottom(new BigInteger(bottom)); } if (StringUtils.isNotBlank(left)) { pg.setLeft(new BigInteger(left)); } if (StringUtils.isNotBlank(right)) { pg.setRight(new BigInteger(right)); } } /** * @Description: 设置行号 * @param distance * :距正文距离 1厘米=567 * @param start * :起始编号(0开始) * @param countBy * :行号间隔 * @param restartType * :STLineNumberRestart.CONTINUOUS(continuous连续编号)
* STLineNumberRestart.NEW_PAGE(每页重新编号)
* STLineNumberRestart.NEW_SECTION(每节重新编号)
*/ public static void setDocInNumType(WordprocessingMLPackage wordPackage, String countBy, String distance, String start, STLineNumberRestart restartType) { SectPr sectPr = getDocSectPr(wordPackage); CTLineNumber lnNumType = sectPr.getLnNumType(); if (lnNumType == null) { lnNumType = new CTLineNumber(); sectPr.setLnNumType(lnNumType); } if (StringUtils.isNotBlank(countBy)) { lnNumType.setCountBy(new BigInteger(countBy)); } if (StringUtils.isNotBlank(distance)) { lnNumType.setDistance(new BigInteger(distance)); } if (StringUtils.isNotBlank(start)) { lnNumType.setStart(new BigInteger(start)); } if (restartType != null) { lnNumType.setRestart(restartType); } } /** * @Description:设置文字方向 tbRl 垂直 */ public static void setDocTextDirection(WordprocessingMLPackage wordPackage, String textDirection) { if (StringUtils.isNotBlank(textDirection)) { SectPr sectPr = getDocSectPr(wordPackage); TextDirection textDir = sectPr.getTextDirection(); if (textDir == null) { textDir = new TextDirection(); sectPr.setTextDirection(textDir); } textDir.setVal(textDirection); } } /** * @Description:设置word 垂直对齐方式(Word默认方式都是"顶端对齐") */ public static void setDocVAlign(WordprocessingMLPackage wordPackage, STVerticalJc valignType) { if (valignType != null) { SectPr sectPr = getDocSectPr(wordPackage); CTVerticalJc valign = sectPr.getVAlign(); if (valign == null) { valign = new CTVerticalJc(); sectPr.setVAlign(valign); } valign.setVal(valignType); } } /** * @Description:获取文档的可用宽度 */ public static int getWritableWidth(WordprocessingMLPackage wordPackage) throws Exception { return wordPackage.getDocumentModel().getSections().get(0).getPageDimensions().getWritableWidthTwips(); } }

 

你可能感兴趣的:(【docx4j】docx4j操作docx,实现替换内容、转换pdf、html等操作)