zoukankan      html  css  js  c++  java
  • 【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方法进行保存,否则修改不生效。

    最后文件内容:

    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内容中。

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

    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<Object> 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;
        }

    结果:

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

    (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);
        }

    结果:

    关于表格合并或者更加复杂的操作参考: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<Object> trs = table.getContent();
                System.out.println(trs);
                System.out.println("=====================");
    
                for (Object obj : trs) {
                    Tr tr = (Tr) obj;// 获取到tr
                    List<Object> content = tr.getContent();
                    System.out.println(content);
                    List<Object> 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<Object> getAllElementFromObject(Object obj, Class<?> toSearch) {
            List<Object> result = new ArrayList<Object>();
            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,如下:

    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里面自带的optionalexport-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<String, String> mappings = new HashMap<String, String>();
            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));
            }
        }

    模板:

    结果:

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

    最后的结果:

     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<Map<String, Object>> dataList = getDataList();
                for (Map<String, Object> 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<Map<String, Object>> 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;
        }
    }

    结果:

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

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

     代码:

    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<Object> 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<Object> 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);
        }

    结果:

    工具栏:

    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("<w:hyperlink r:id="");
            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("<w:r><w:rPr><w:rStyle w:val="Hyperlink" />");
            sb.append("<w:rFonts  w:ascii="");
            sb.append(enFontName);
            sb.append(""  w:hAnsi="");
            sb.append(enFontName);
            sb.append(""  w:eastAsia="");
            sb.append(cnFontName);
            sb.append("" w:hint="eastAsia"/>");
            sb.append("<w:sz w:val="");
            sb.append(fontSize);
            sb.append(""/><w:szCs w:val="");
            sb.append(fontSize);
            sb.append(""/></w:rPr><w:t>");
            sb.append(value);
            sb.append("</w:t></w:r></w:hyperlink>");
    
            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<Object> getAllElementFromObject(Object obj, Class<?> toSearch) {
            List<Object> result = new ArrayList<Object>();
            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<Tr> trList = getTblAllTr(tbl);
            if (row > trList.size()) {
                return;
            }
            Tr tr = trList.get(row);
            List<Tc> 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<Tr> trList = getTblAllTr(tbl);
            if (row > trList.size()) {
                return;
            }
            Tr tr = trList.get(row);
            List<Tc> 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<Tr> trList = getTblAllTr(tbl);
            if (row >= trList.size()) {
                return null;
            }
            List<Tc> tcList = getTrAllCell(trList.get(row));
            if (cell >= tcList.size()) {
                return null;
            }
            return tcList.get(cell);
        }
    
        /**
         * @Description:得到所有表格
         */
        public static List<Tbl> getAllTbl(WordprocessingMLPackage wordMLPackage) {
            MainDocumentPart mainDocPart = wordMLPackage.getMainDocumentPart();
            List<Object> objList = getAllElementFromObject(mainDocPart, Tbl.class);
            if (objList == null) {
                return null;
            }
            List<Tbl> tblList = new ArrayList<Tbl>();
            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<Object> 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<String> getTblContentList(Tbl tbl) throws Exception {
            List<String> resultList = new ArrayList<String>();
            List<Tr> trList = getTblAllTr(tbl);
            for (Tr tr : trList) {
                StringBuffer sb = new StringBuffer();
                List<Tc> 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("<w:tblPr ").append(Namespaces.W_NAMESPACE_DECLARATION).append(">");
            tblSb.append("<w:tblStyle w:val="TableGrid"/>");
            tblSb.append("<w:tblW w:w="0" w:type="auto"/>");
            // 上边框
            tblSb.append("<w:tblBorders>");
            tblSb.append("<w:top w:val="single" w:sz="1" w:space="0" w:color="auto"/>");
            // 左边框
            tblSb.append("<w:left w:val="single" w:sz="1" w:space="0" w:color="auto"/>");
            // 下边框
            tblSb.append("<w:bottom w:val="single" w:sz="1" w:space="0" w:color="auto"/>");
            // 右边框
            tblSb.append("<w:right w:val="single" w:sz="1" w:space="0" w:color="auto"/>");
            tblSb.append("<w:insideH w:val="single" w:sz="1" w:space="0" w:color="auto"/>");
            tblSb.append("<w:insideV w:val="single" w:sz="1" w:space="0" w:color="auto"/>");
            tblSb.append("</w:tblBorders>");
            tblSb.append("</w:tblPr>");
            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<Tr> trList = getTblAllTr(tbl);
                for (Tr tr : trList) {
                    List<Tc> tcList = getTrAllCell(tr);
                    for (Tc tc : tcList) {
                        setTcJcAlign(tc, jcType);
                    }
                }
            }
        }
    
        /**
         * @Description: 设置表格垂直对齐方式(包括单元格),只对该方法前面产生的单元格起作用
         */
        public static void setTblAllVAlign(Tbl tbl, STVerticalJc vAlignType) {
            if (vAlignType != null) {
                List<Tr> trList = getTblAllTr(tbl);
                for (Tr tr : trList) {
                    List<Tc> 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<Tr> getTblAllTr(Tbl tbl) {
            List<Object> objList = getAllElementFromObject(tbl, Tr.class);
            List<Tr> trList = new ArrayList<Tr>();
            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<TblGridCol> 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<Tc> 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<Object> 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<Tc> 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<P> pList = getTcAllP(tc);
            for (P p : pList) {
                PPr ppr = getPPr(p);
                List<Object> 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<P> getTcAllP(Tc tc) {
            List<Object> objList = getAllElementFromObject(tc, P.class);
            List<P> pList = new ArrayList<P>();
            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<P> 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<Tc> getTrAllCell(Tr tr) {
            List<Object> objList = getAllElementFromObject(tr, Tc.class);
            List<Tc> tcList = new ArrayList<Tc>();
            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<Object> 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<Object> 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("
    ");
                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<Object> 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<Object> 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<Object> 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<Object> getObjectByXpath(WordprocessingMLPackage wordMLPackage, String xpath) throws Exception {
            final List<Object> 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<Object> 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<Object> 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("
    ");
                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("
    ");
                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连续编号)<br/>
         *            STLineNumberRestart.NEW_PAGE(每页重新编号)<br/>
         *            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();
        }
    
    }
  • 相关阅读:
    1860 最大数
    1164 统计数字
    1063 合并果子
    1098 均分纸牌
    2806 红与黑
    1168 火柴棒等式
    1910 递归函数
    2774 火烧赤壁
    2017.0705.《计算机组成原理》-存储器
    2017.0704.《计算机组成原理》-动态RAM
  • 原文地址:https://www.cnblogs.com/qlqwjy/p/9866484.html
Copyright © 2011-2022 走看看