为您推荐:
精华内容
最热下载
问答
  • 5星
    15KB qq_33657870 2021-06-05 14:32:11
  • 5星
    406KB qq_42294351 2021-07-14 17:28:51
  • 5星
    3.47MB qq_45949479 2021-01-31 16:02:59
  • 5星
    1.44MB xueyunshengling 2021-06-28 13:23:35
  • 5星
    18KB m0_52957036 2020-05-21 21:47:36
  • 5星
    50KB weixin_40111182 2021-01-26 17:39:55
  • 5星
    14.36MB weixin_42535005 2021-07-21 21:52:32
  • 5星
    678KB qq_44809707 2021-06-17 14:07:32
  • 5星
    151KB a750186040 2021-07-09 18:56:53
  • 5星
    215KB licbc 2021-06-08 08:44:24
  • 前段时间调研POI和docx4jword的操作,结合网上其他大佬的代码,自己补充写了并整合HTML转word的相关的公用方法。 用到的jar包 ‘org.docx4j:docx4j:6.0.1’, ‘org.docx4j:xhtmlrenderer:3.0.0’, ‘org.docx4...

    前段时间调研POI和docx4j对word的操作,结合网上其他大佬的代码,自己补充写了并整合HTML转word的相关的公用方法。

    用到的jar包
    ‘org.docx4j:docx4j:6.0.1’,
    ‘org.docx4j:xhtmlrenderer:3.0.0’,
    ‘org.docx4j:xmlgraphics-commons:2.3’,
    ‘org.docx4j:docx4j-ImportXHTML:6.0.1’,

    import org.apache.commons.lang.StringUtils;
    import org.docx4j.convert.in.xhtml.XHTMLImporterImpl;
    import org.docx4j.jaxb.Context;
    import org.docx4j.model.structure.PageSizePaper;
    import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
    import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
    import org.docx4j.wml.*;
    import org.jsoup.Jsoup;
    import org.jsoup.select.Elements;
    
    import javax.xml.bind.JAXBElement;
    import java.math.BigInteger;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * Created by Administrator on 2019/9/3.
     */
    public class Docx4jWord {
    
        private WordprocessingMLPackage wordMLPackage = null;
        private MainDocumentPart mp = null;
        private ObjectFactory factory = null;
    
        private Docx4jWord(WordprocessingMLPackage wordMLPackage) {
            this.wordMLPackage = wordMLPackage;
            this.mp = wordMLPackage.getMainDocumentPart();
            this.factory = Context.getWmlObjectFactory();
        }
    
        public static Docx4jWord createWord() throws Exception {
            WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
            return new Docx4jWord(wordMLPackage);
        }
    
        public static Docx4jWord createWord(PageSizePaper pageSizePaper, Boolean formatType) throws Exception {
            WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage(pageSizePaper, formatType);
            return new Docx4jWord(wordMLPackage);
        }
    
        public WordprocessingMLPackage getWordMLPackage() {
            return wordMLPackage;
        }
    
        public MainDocumentPart getMp() {
            return mp;
        }
    
        public void setMp(MainDocumentPart mp) {
            this.mp = mp;
        }
    
        public ObjectFactory getFactory() {
            return factory;
        }
    
        public void setFactory(ObjectFactory factory) {
            this.factory = factory;
        }
    
    
        //以下为生成Word通用方法/
    
        /**
         * 解决解析html里不识别 
         *
         * @param html
         * @return
         * @throws Exception
         */
    public String setHTMLHead(String html) throws Exception {
            html = "<!DOCTYPE html [<!ENTITY nbsp \"&#160;\"><!ENTITY iexcl \"&#161;\"><!ENTITY cent \"&#162;\"><!ENTITY pound \"&#163;\"><!ENTITY curren \"&#164;\"><!ENTITY yen \"&#165;\"><!ENTITY brvbar \"&#166;\"><!ENTITY sect \"&#167;\"><!ENTITY uml \"&#168;\"><!ENTITY copy \"&#169;\"><!ENTITY ordf \"&#170;\"><!ENTITY laquo \"&#171;\"><!ENTITY not \"&#172;\"><!ENTITY shy \"&#173;\"><!ENTITY reg \"&#174;\"><!ENTITY macr \"&#175;\"><!ENTITY deg \"&#176;\"><!ENTITY plusmn \"&#177;\"><!ENTITY sup2 \"&#178;\"><!ENTITY sup3 \"&#179;\"><!ENTITY acute \"&#180;\"><!ENTITY micro \"&#181;\"><!ENTITY para \"&#182;\"><!ENTITY middot \"&#183;\"><!ENTITY cedil \"&#184;\"><!ENTITY sup1 \"&#185;\"><!ENTITY ordm \"&#186;\"><!ENTITY raquo \"&#187;\"><!ENTITY frac14 \"&#188;\"><!ENTITY frac12 \"&#189;\"><!ENTITY frac34 \"&#190;\"><!ENTITY iquest \"&#191;\"><!ENTITY Agrave \"&#192;\"><!ENTITY Aacute \"&#193;\"><!ENTITY Acirc \"&#194;\"><!ENTITY Atilde \"&#195;\"><!ENTITY Auml \"&#196;\"><!ENTITY Aring \"&#197;\"><!ENTITY AElig \"&#198;\"><!ENTITY Ccedil \"&#199;\"><!ENTITY Egrave \"&#200;\"><!ENTITY Eacute \"&#201;\"><!ENTITY Ecirc \"&#202;\"><!ENTITY Euml \"&#203;\"><!ENTITY Igrave \"&#204;\"><!ENTITY Iacute \"&#205;\"><!ENTITY Icirc \"&#206;\"><!ENTITY Iuml \"&#207;\"><!ENTITY ETH \"&#208;\"><!ENTITY Ntilde \"&#209;\"><!ENTITY Ograve \"&#210;\"><!ENTITY Oacute \"&#211;\"><!ENTITY Ocirc \"&#212;\"><!ENTITY Otilde \"&#213;\"><!ENTITY Ouml \"&#214;\"><!ENTITY times \"&#215;\"><!ENTITY Oslash \"&#216;\"><!ENTITY Ugrave \"&#217;\"><!ENTITY Uacute \"&#218;\"><!ENTITY Ucirc \"&#219;\"><!ENTITY Uuml \"&#220;\"><!ENTITY Yacute \"&#221;\"><!ENTITY THORN \"&#222;\"><!ENTITY szlig \"&#223;\"><!ENTITY agrave \"&#224;\"><!ENTITY aacute \"&#225;\"><!ENTITY acirc \"&#226;\"><!ENTITY atilde \"&#227;\"><!ENTITY auml \"&#228;\"><!ENTITY aring \"&#229;\"><!ENTITY aelig \"&#230;\"><!ENTITY ccedil \"&#231;\"><!ENTITY egrave \"&#232;\"><!ENTITY eacute \"&#233;\"><!ENTITY ecirc \"&#234;\"><!ENTITY euml \"&#235;\"><!ENTITY igrave \"&#236;\"><!ENTITY iacute \"&#237;\"><!ENTITY icirc \"&#238;\"><!ENTITY iuml \"&#239;\"><!ENTITY eth \"&#240;\"><!ENTITY ntilde \"&#241;\"><!ENTITY ograve \"&#242;\"><!ENTITY oacute \"&#243;\"><!ENTITY ocirc \"&#244;\"><!ENTITY otilde \"&#245;\"><!ENTITY ouml \"&#246;\"><!ENTITY divide \"&#247;\"><!ENTITY oslash \"&#248;\"><!ENTITY ugrave \"&#249;\"><!ENTITY uacute \"&#250;\"><!ENTITY ucirc \"&#251;\"><!ENTITY uuml \"&#252;\"><!ENTITY yacute \"&#253;\"><!ENTITY thorn \"&#254;\"><!ENTITY yuml \"&#255;\"><!ENTITY fnof \"&#402;\"><!ENTITY Alpha \"&#913;\"><!ENTITY Beta \"&#914;\"><!ENTITY Gamma \"&#915;\"><!ENTITY Delta \"&#916;\"><!ENTITY Epsilon \"&#917;\"><!ENTITY Zeta \"&#918;\"><!ENTITY Eta \"&#919;\"><!ENTITY Theta \"&#920;\"><!ENTITY Iota \"&#921;\"><!ENTITY Kappa \"&#922;\"><!ENTITY Lambda \"&#923;\"><!ENTITY Mu \"&#924;\"><!ENTITY Nu \"&#925;\"><!ENTITY Xi \"&#926;\"><!ENTITY Omicron \"&#927;\"><!ENTITY Pi \"&#928;\"><!ENTITY Rho \"&#929;\"><!ENTITY Sigma \"&#931;\"><!ENTITY Tau \"&#932;\"><!ENTITY Upsilon \"&#933;\"><!ENTITY Phi \"&#934;\"><!ENTITY Chi \"&#935;\"><!ENTITY Psi \"&#936;\"><!ENTITY Omega \"&#937;\"><!ENTITY alpha \"&#945;\"><!ENTITY beta \"&#946;\"><!ENTITY gamma \"&#947;\"><!ENTITY delta \"&#948;\"><!ENTITY epsilon \"&#949;\"><!ENTITY zeta \"&#950;\"><!ENTITY eta \"&#951;\"><!ENTITY theta \"&#952;\"><!ENTITY iota \"&#953;\"><!ENTITY kappa \"&#954;\"><!ENTITY lambda \"&#955;\"><!ENTITY mu \"&#956;\"><!ENTITY nu \"&#957;\"><!ENTITY xi \"&#958;\"><!ENTITY omicron \"&#959;\"><!ENTITY pi \"&#960;\"><!ENTITY rho \"&#961;\"><!ENTITY sigmaf \"&#962;\"><!ENTITY sigma \"&#963;\"><!ENTITY tau \"&#964;\"><!ENTITY upsilon \"&#965;\"><!ENTITY phi \"&#966;\"><!ENTITY chi \"&#967;\"><!ENTITY psi \"&#968;\"><!ENTITY omega \"&#969;\"><!ENTITY thetasym \"&#977;\"><!ENTITY upsih \"&#978;\"><!ENTITY piv \"&#982;\"><!ENTITY bull \"&#8226;\"><!ENTITY hellip \"&#8230;\"><!ENTITY prime \"&#8242;\"><!ENTITY Prime \"&#8243;\"><!ENTITY oline \"&#8254;\"><!ENTITY frasl \"&#8260;\"><!ENTITY weierp \"&#8472;\"><!ENTITY image \"&#8465;\"><!ENTITY real \"&#8476;\"><!ENTITY trade \"&#8482;\"><!ENTITY alefsym \"&#8501;\"><!ENTITY larr \"&#8592;\"><!ENTITY uarr \"&#8593;\"><!ENTITY rarr \"&#8594;\"><!ENTITY darr \"&#8595;\"><!ENTITY harr \"&#8596;\"><!ENTITY crarr \"&#8629;\"><!ENTITY lArr \"&#8656;\"><!ENTITY uArr \"&#8657;\"><!ENTITY rArr \"&#8658;\"><!ENTITY dArr \"&#8659;\"><!ENTITY hArr \"&#8660;\"><!ENTITY forall \"&#8704;\"><!ENTITY part \"&#8706;\"><!ENTITY exist \"&#8707;\"><!ENTITY empty \"&#8709;\"><!ENTITY nabla \"&#8711;\"><!ENTITY isin \"&#8712;\"><!ENTITY notin \"&#8713;\"><!ENTITY ni \"&#8715;\"><!ENTITY prod \"&#8719;\"><!ENTITY sum \"&#8721;\"><!ENTITY minus \"&#8722;\"><!ENTITY lowast \"&#8727;\"><!ENTITY radic \"&#8730;\"><!ENTITY prop \"&#8733;\"><!ENTITY infin \"&#8734;\"><!ENTITY ang \"&#8736;\"><!ENTITY and \"&#8743;\"><!ENTITY or \"&#8744;\"><!ENTITY cap \"&#8745;\"><!ENTITY cup \"&#8746;\"><!ENTITY int \"&#8747;\"><!ENTITY there4 \"&#8756;\"><!ENTITY sim \"&#8764;\"><!ENTITY cong \"&#8773;\"><!ENTITY asymp \"&#8776;\"><!ENTITY ne \"&#8800;\"><!ENTITY equiv \"&#8801;\"><!ENTITY le \"&#8804;\"><!ENTITY ge \"&#8805;\"><!ENTITY sub \"&#8834;\"><!ENTITY sup \"&#8835;\"><!ENTITY nsub \"&#8836;\"><!ENTITY sube \"&#8838;\"><!ENTITY supe \"&#8839;\"><!ENTITY oplus \"&#8853;\"><!ENTITY otimes \"&#8855;\"><!ENTITY perp \"&#8869;\"><!ENTITY sdot \"&#8901;\"><!ENTITY lceil \"&#8968;\"><!ENTITY rceil \"&#8969;\"><!ENTITY lfloor \"&#8970;\"><!ENTITY rfloor \"&#8971;\"><!ENTITY lang \"&#9001;\"><!ENTITY rang \"&#9002;\"><!ENTITY loz \"&#9674;\"><!ENTITY spades \"&#9824;\"><!ENTITY clubs \"&#9827;\"><!ENTITY hearts \"&#9829;\"><!ENTITY diams \"&#9830;\"><!ENTITY quot \"&#34;\"><!ENTITY amp \"&#38;\"><!ENTITY lt \"&#60;\"><!ENTITY gt \"&#62;\"><!ENTITY OElig \"&#338;\"><!ENTITY oelig \"&#339;\"><!ENTITY Scaron \"&#352;\"><!ENTITY scaron \"&#353;\"><!ENTITY Yuml \"&#376;\"><!ENTITY circ \"&#710;\"><!ENTITY tilde \"&#732;\"><!ENTITY ensp \"&#8194;\"><!ENTITY emsp \"&#8195;\"><!ENTITY thinsp \"&#8201;\"><!ENTITY zwnj \"&#8204;\"><!ENTITY zwj \"&#8205;\"><!ENTITY lrm \"&#8206;\"><!ENTITY rlm \"&#8207;\"><!ENTITY ndash \"&#8211;\"><!ENTITY mdash \"&#8212;\"><!ENTITY lsquo \"&#8216;\"><!ENTITY rsquo \"&#8217;\"><!ENTITY sbquo \"&#8218;\"><!ENTITY ldquo \"&#8220;\"><!ENTITY rdquo \"&#8221;\"><!ENTITY bdquo \"&#8222;\"><!ENTITY dagger \"&#8224;\"><!ENTITY Dagger \"&#8225;\"><!ENTITY permil \"&#8240;\"><!ENTITY lsaquo \"&#8249;\"><!ENTITY rsaquo \"&#8250;\"><!ENTITY euro \"&#8364;\">\n]>\n" + html;
            return new String(html.getBytes(), "GB2312");
        }
    
        /**
         * 格式化html
         *
         * @param element
         * @param basePath
         * @throws Exception
         */
        public void convertReportHtml(org.jsoup.nodes.Element element, String basePath) throws Exception {
            if (element.id().equals("customerImg")) {
                element.remove();
                return;
            }
    
            String tagName = element.tagName();
            if (tagName.equals("table") && !"printTable".equals(element.id())) { //printTable 是需求版本输出Word时,用于布局的表格,不应该显示边框
                String style = element.attr("style");
                style += "width: 100%; border:1px solid #CCC; border-collapse:collapse;";
                element.attr("style", style);
            } else if (tagName.equals("th") && !"printTable".equals(element.parent().parent().parent().id())) {
                String style = element.attr("style");
                style += " border:1px solid #CCC;";
                element.attr("style", style);
            } else if (tagName.equals("td") && !"printTable".equals(element.parent().parent().parent().id())) {
                String style = element.attr("style");
                style += " border:1px solid #EEE;";
                element.attr("style", style);
            } else if (tagName.equals("img")) {
                String src = element.attr("src");
                if (!src.startsWith("http")) {
                    src = basePath + src;
                    element.attr("src", src);
                }
                if (src.contains("svg") && src.contains("version")) {//如果highchart图表,先删除掉
                    element.remove();
                    return;
                }
            } else if (tagName.equals("a")) {
                String href = element.attr("href");
                if (!href.startsWith("http")) {
                    href = basePath + href;
                    element.attr("href", href);
                }
            }
    
            Elements elements = element.children();
            if (elements.isEmpty()) {
                return;
            }
    
            for (org.jsoup.nodes.Element e : elements) {
                convertReportHtml(e, basePath);
            }
        }
    
        /**
         * 将html转成段落
         */
        public void html2WordWithParagram(String htmlContent, String basePath) throws Exception {
            org.jsoup.nodes.Document document = Jsoup.parse(htmlContent, basePath);
            convertReportHtml(document, basePath);
            String html = document.toString();
            html = setHTMLHead(html);
            RPr rpr = getRPr("宋体", "000000", "22",
                    STHint.EAST_ASIA, false, false, false, false);
            P p = factory.createP();
            setParagraphSpacing(p, JcEnumeration.CENTER, true, "100", "100", null,
                    null, true, "240", STLineSpacingRule.AUTO);
            R run = factory.createR();
            // 设置表格内容字体样式
            run.setRPr(rpr);
            XHTMLImporterImpl XHTMLImporter = new XHTMLImporterImpl(wordMLPackage);
            run.getContent().addAll(XHTMLImporter.convert(html, null));
            p.getContent().add(run);
            mp.addObject(p);
        }
    
        /**
         * 将html生成文档
         */
        public void html2WordWithDocument(String html) throws Exception {
            XHTMLImporterImpl XHTMLImporter = new XHTMLImporterImpl(wordMLPackage);
            wordMLPackage.getMainDocumentPart().getContent().addAll(
                    XHTMLImporter.convert(html, null));
        }
    
        /**
         * 写标题或段落
         */
        public void addParagraph(String txtValue, boolean isTitle, int fontSize, boolean isBlod) throws Exception {
            RPr rpr;
            JcEnumeration jcEnumeration;
    
            if (isTitle) {
                rpr = getRPr("微软雅黑", "000000", fontSize + "", STHint.EAST_ASIA,
                        isBlod, false, false, false);
                jcEnumeration = JcEnumeration.CENTER;
            } else {
                rpr = getRPr("宋体", "000000", fontSize + "", STHint.EAST_ASIA,
                        isBlod, false, false, false);
                jcEnumeration = JcEnumeration.LEFT;
            }
    
            Text txt = factory.createText();
            txt.setValue(txtValue);
            R run = factory.createR();
            run.getContent().add(txt);
            run.setRPr(rpr);
    
            P paragraph = factory.createP();
            paragraph.getContent().add(run);
            setParagraphSpacing(paragraph, jcEnumeration, true,
                    "0", "0", null, null, true, "240", STLineSpacingRule.AUTO);
            mp.addObject(paragraph);
        }
    
        /**
         * 根据等级设置字体
         *
         * @param level
         */
        public RPr getRPrByHeadLevel(int level) {
            int fontSize = 30 - level;
            RPr rpr = getRPr("宋体", "000000", fontSize + "", STHint.EAST_ASIA,
                    level <= 1, false, false, false);
            return rpr;
        }
    
        /**
         * 添加段落
         *
         * @param paragraph
         * @throws Exception
         */
        public void addParagraph(P paragraph) throws Exception {
            mp.addObject(paragraph);
        }
    
        /**
         * 分割线
         */
        public void createLine() {
            addPageBreak(STBrType.TEXT_WRAPPING);
            CTBorder topBorder = new CTBorder();
            topBorder.setSpace(new BigInteger("1"));
            topBorder.setSz(new BigInteger("1"));
            topBorder.setVal(STBorder.SINGLE);
            P p = factory.createP();
            PPr ppr = new PPr();
            PPrBase.PBdr pBdr = new PPrBase.PBdr();
            pBdr.setTop(topBorder);
            ppr.setPBdr(pBdr);
            p.setPPr(ppr);
            mp.addObject(p);
        }
    
    
        // 设置段间距-->行距 段前段后距离
        // 段前段后可以设置行和磅 行距只有磅
        // 段前磅值和行值同时设置,只有行值起作用
        // TODO 1磅=20 1行=100 单倍行距=240 为什么是这个值不知道
    
        /**
         * @param jcEnumeration     对齐方式
         * @param isSpace           是否设置段前段后值
         * @param before            段前磅数
         * @param after             段后磅数
         * @param beforeLines       段前行数
         * @param afterLines        段后行数
         * @param isLine            是否设置行距
         * @param lineValue         行距值
         * @param sTLineSpacingRule 自动auto 固定exact 最小 atLeast
         */
        public void setParagraphSpacing(P p, JcEnumeration jcEnumeration, boolean isSpace, String before, String after,
                                        String beforeLines, String afterLines, boolean isLine, String lineValue, STLineSpacingRule sTLineSpacingRule) {
            PPr pPr = p.getPPr();
            if (pPr == null) {
                pPr = factory.createPPr();
            }
            Jc jc = pPr.getJc();
            if (jc == null) {
                jc = new Jc();
            }
            jc.setVal(jcEnumeration);
            pPr.setJc(jc);
    
            PPrBase.Spacing spacing = new PPrBase.Spacing();
            if (isSpace) {
                if (before != null) {
                    // 段前磅数
                    spacing.setBefore(new BigInteger(before));
                }
                if (after != null) {
                    // 段后磅数
                    spacing.setAfter(new BigInteger(after));
                }
                if (beforeLines != null) {
                    // 段前行数
                    spacing.setBeforeLines(new BigInteger(beforeLines));
                }
                if (afterLines != null) {
                    // 段后行数
                    spacing.setAfterLines(new BigInteger(afterLines));
                }
            }
            if (isLine) {
                if (lineValue != null) {
                    spacing.setLine(new BigInteger(lineValue));
                }
                spacing.setLineRule(sTLineSpacingRule);
            }
            pPr.setSpacing(spacing);
            p.setPPr(pPr);
        }
    
    
        /**
         * 创建字体
         *
         * @param isBlod      粗体
         * @param isUnderLine 下划线
         * @param isItalic    斜体
         * @param isStrike    删除线
         */
        public RPr getRPr(String fontFamily, String colorVal, String fontSize, STHint sTHint, boolean isBlod,
                          boolean isUnderLine, boolean isItalic, boolean isStrike) {
            RPr rPr = factory.createRPr();
            RFonts rf = new RFonts();
            rf.setHint(sTHint);
            rf.setAscii(fontFamily);
            rf.setHAnsi(fontFamily);
            rPr.setRFonts(rf);
    
            BooleanDefaultTrue bdt = factory.createBooleanDefaultTrue();
            rPr.setBCs(bdt);
            if (isBlod) {
                rPr.setB(bdt);
            }
            if (isItalic) {
                rPr.setI(bdt);
            }
            if (isStrike) {
                rPr.setStrike(bdt);
            }
            if (isUnderLine) {
                U underline = new U();
                underline.setVal(UnderlineEnumeration.SINGLE);
                rPr.setU(underline);
            }
    
            Color color = new Color();
            color.setVal(colorVal);
            rPr.setColor(color);
    
            HpsMeasure sz = new HpsMeasure();
            sz.setVal(new BigInteger(fontSize));
            rPr.setSz(sz);
            rPr.setSzCs(sz);
            return rPr;
        }
    
    
        // 分页
        public void addPageBreak(STBrType sTBrType) {
            MainDocumentPart documentPart = wordMLPackage.getMainDocumentPart();
            Br breakObj = new Br();
            breakObj.setType(sTBrType);
            P paragraph = factory.createP();
            paragraph.getContent().add(breakObj);
            documentPart.addObject(paragraph);
        }
    
        // 得到页面宽度
        public int getWritableWidth()
                throws Exception {
            return wordMLPackage.getDocumentModel().getSections().get(0)
                    .getPageDimensions().getWritableWidthTwips();
        }
    
    
        /**
         * 表格占页面宽度
         */
        public void setTableGridCol(Tbl table, int colSize) throws Exception {
            TblGrid tblGrid = factory.createTblGrid();
            for (int i = 0; i < colSize; i++) {
                TblGridCol gridCol = factory.createTblGridCol();
                gridCol.setW(BigInteger.valueOf(2256));
                tblGrid.getGridCol().add(gridCol);
            }
            table.setTblGrid(tblGrid);
    
            TblPr tblPr = table.getTblPr();
            if (tblPr == null) {
                tblPr = factory.createTblPr();
            }
            TblWidth tblWidth = new TblWidth();
            tblWidth.setType("dxa");// 这一行是必须的,不自己设置宽度默认是auto
            tblWidth.setW(new BigInteger("9027"));
            tblPr.setTblW(tblWidth);
            table.setTblPr(tblPr);
        }
    
        // 表格水平对齐方式
        public void setTableAlign(Tbl table,
                                  JcEnumeration jcEnumeration) {
            TblPr tablePr = table.getTblPr();
            if (tablePr == null) {
                tablePr = factory.createTblPr();
            }
            Jc jc = tablePr.getJc();
            if (jc == null) {
                jc = new Jc();
            }
            jc.setVal(jcEnumeration);
            tablePr.setJc(jc);
            table.setTblPr(tablePr);
        }
    
    
        // 表格增加边框 可以设置上下左右四个边框样式以及横竖水平线样式
        public void addBorders(Tbl table, CTBorder topBorder, CTBorder bottomBorder, CTBorder leftBorder, CTBorder rightBorder,
                               CTBorder hBorder, CTBorder vBorder) {
            table.setTblPr(new TblPr());
            TblBorders borders = new TblBorders();
            borders.setBottom(bottomBorder);
            borders.setLeft(leftBorder);
            borders.setRight(rightBorder);
            borders.setTop(topBorder);
            borders.setInsideH(hBorder);
            borders.setInsideV(vBorder);
            table.getTblPr().setTblBorders(borders);
        }
    
    
        public 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) {
                    TcPrInner.GridSpan gridSpan = tcPr.getGridSpan();
                    if (gridSpan == null) {
                        gridSpan = new TcPrInner.GridSpan();
                        tcPr.setGridSpan(gridSpan);
                    }
                    gridSpan.setVal(BigInteger.valueOf(Math.min(tcList.size() - 1,
                            toCell) - fromCell + 1));
                } else {
                    tr.getContent().remove(cellIndex);
                }
            }
        }
    
        /**
         * 跨列合并
         */
        public void mergeCellsHorizontal(Tbl tbl, int row, int fromCell, int toCell, TblWidth tblWidth) {
            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);
            Tc cell = tcList.get(0);
            TcPr cellPr = getTcPr(cell);
            cellPr.setTcW(tblWidth);
            for (int cellIndex = fromCell, len = Math
                    .min(tcList.size() - 1, toCell); cellIndex <= len; cellIndex++) {
                Tc tc = tcList.get(cellIndex);
                TcPr tcPr = getTcPr(tc);
                TcPrInner.HMerge hMerge = tcPr.getHMerge();
                if (hMerge == null) {
                    hMerge = new TcPrInner.HMerge();
                    tcPr.setHMerge(hMerge);
                }
                if (cellIndex == fromCell) {
                    hMerge.setVal("restart");
                } else {
                    hMerge.setVal("continue");
                }
            }
        }
    
        /**
         * 跨行合并
         */
        public 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);
                TcPrInner.VMerge vMerge = tcPr.getVMerge();
                if (vMerge == null) {
                    vMerge = new TcPrInner.VMerge();
                    tcPr.setVMerge(vMerge);
                }
                if (rowIndex == fromRow) {
                    vMerge.setVal("restart");
                } else {
                    vMerge.setVal("continue");
                }
            }
        }
    
        /**
         * 得到指定位置的表格
         */
        public 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);
        }
    
        /**
         * 获取所有的单元格
         */
        public 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;
        }
    
        public static TcPr getTcPr(Tc tc) {
            TcPr tcPr = tc.getTcPr();
            if (tcPr == null) {
                tcPr = new TcPr();
                tc.setTcPr(tcPr);
            }
            return tcPr;
        }
    
        /**
         * 得到表格所有的行
         */
        public 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;
        }
    
        /**
         * 得到指定类型的元素
         */
        public 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;
        }
    
    
        /**
         * 栏目内容(表格)
         */
        public void createNormalTable(List<String[]> tableValue, String basePath) throws Exception {
            RPr titleRpr = getRPr("宋体", "000000", "22", STHint.EAST_ASIA,
                    true, false, false, false);
            RPr contentRpr = getRPr("宋体", "000000", "22",
                    STHint.EAST_ASIA, false, false, false, false);
            Tbl table = factory.createTbl();
            CTBorder topBorder = new CTBorder();
            topBorder.setVal(STBorder.DOUBLE);
            topBorder.setSz(new BigInteger("2"));
            CTBorder leftBorder = new CTBorder();
            leftBorder.setVal(STBorder.NONE);
            leftBorder.setSz(new BigInteger("0"));
    
            CTBorder hBorder = new CTBorder();
            hBorder.setVal(STBorder.SINGLE);
            hBorder.setSz(new BigInteger("1"));
    
            addBorders(table, topBorder, topBorder, leftBorder, leftBorder, hBorder, null);
    
            setTableGridCol(table, 4);
    
            String[] colorStr = new String[]{"E3E3E3", "D3D3D3"};
    
            for (int i = 0; i < tableValue.size(); i++) {
    
                String[] trValue = tableValue.get(i);
    
                Tr contentRow = factory.createTr();
    
                addTableCell(contentRow, StringUtils.isNotBlank(trValue[0]) ? trValue[0] : "", titleRpr,
                        JcEnumeration.CENTER, true, colorStr[i % 2], basePath);
                addTableCell(contentRow, StringUtils.isNotBlank(trValue[1]) ? trValue[1] : "", contentRpr,
                        JcEnumeration.LEFT, true, colorStr[i % 2], basePath);
                addTableCell(contentRow, StringUtils.isNotBlank(trValue[2]) ? trValue[2] : "", titleRpr,
                        JcEnumeration.CENTER, true, colorStr[i % 2], basePath);
                addTableCell(contentRow, StringUtils.isNotBlank(trValue[3]) ? trValue[3] : "", contentRpr,
                        JcEnumeration.LEFT, true, colorStr[i % 2], basePath);
    
                table.getContent().add(contentRow);
    
                if (!StringUtils.isNotBlank(trValue[2])) {//需要合并
                    TblWidth tblWidth = new TblWidth();
                    tblWidth.setType("dxa");
                    tblWidth.setW(new BigInteger("2256"));
                    mergeCellsHorizontal(table, i, 1, 3, tblWidth);
                }
            }
    
            setTableAlign(table, JcEnumeration.CENTER);
            mp.addObject(table);
        }
    
    
        /**
         * 栏目
         *
         * @param titleColumnName
         * @throws Exception
         */
        public void createTitleColumn(String titleColumnName) throws Exception {
            RPr boldRPr = getRPr("宋体", "000000", "24", STHint.EAST_ASIA,
                    true, false, false, false);
            ObjectFactory factory = getFactory();
            P paragraph = factory.createP();
            Text txt = factory.createText();
            txt.setValue(titleColumnName);
            R run = factory.createR();
            run.getContent().add(txt);
            run.setRPr(boldRPr);
            paragraph.getContent().add(run);
            setParagraphSpacing(paragraph, JcEnumeration.LEFT, true, "0",
                    "0", "200", "100", true, "240", STLineSpacingRule.AUTO);
            mp.addObject(paragraph);
        }
    
        // 新增单元格
        private void addTableCell(Tr tableRow, String content,
                                  RPr rpr, JcEnumeration jcEnumeration, boolean hasBgColor,
                                  String backgroudColor, String basePath) throws Exception {
            Tc tableCell = factory.createTc();
            P p = factory.createP();
            setParagraphSpacing(p, jcEnumeration, true, "100", "100", null,
                    null, true, "240", STLineSpacingRule.AUTO);
    
            TcPr tcPr = tableCell.getTcPr();
            if (tcPr == null) {
                tcPr = factory.createTcPr();
            }
    
            CTVerticalJc valign = factory.createCTVerticalJc();
            valign.setVal(STVerticalJc.CENTER);
            tcPr.setVAlign(valign);
    
            R run = factory.createR();
            // 设置表格内容字体样式
            run.setRPr(rpr);
    
            //写值
            if (content.endsWith("##$html$##")) {
                content = content.replace("##$html$##", "");
                content = content.replace("&nbsp;", " ");
                if (content.contains("servlet/image?f=")) {
                    content = content.replace("servlet/image?f=", basePath + "servlet/image?f=");
                }
                XHTMLImporterImpl XHTMLImporter = new XHTMLImporterImpl(wordMLPackage);
                run.getContent().addAll(XHTMLImporter.convert("<div>" + content + "</div>", null));
                p.getContent().add(run);
                tableCell.getContent().add(p);
            } else {
                Text t = factory.createText();
                t.setValue(content);
                run.getContent().add(t);
                p.getContent().add(run);
                tableCell.getContent().add(p);
            }
    
            if (hasBgColor) {
                CTShd shd = tcPr.getShd();
                if (shd == null) {
                    shd = factory.createCTShd();
                }
                shd.setColor("auto");
                shd.setFill(backgroudColor);
                tcPr.setShd(shd);
            }
            tableCell.setTcPr(tcPr);
            tableRow.getContent().add(tableCell);
        }
    }
    
    

    以上是公用方法,简单使用

    //html转word
    public void exportFormatItemPage(String content, String basePath) throws Exception {
                //创建文档
                Docx4jWord word = Docx4jWord.createWord();
    
                org.jsoup.nodes.Document document = Jsoup.parse(content, basePath);
                word.convertReportHtml(document, basePath);
                String html = document.toString();
                html = word.setHTMLHead(html);
    
                //html转word
                word.html2WordWithDocument(html);
                
    			WordprocessingMLPackage wordMLPackage = word.getWordMLPackage();;
    			
                wordMLPackage.save(outputStream());
        }
    
    
    	//写word
    	public WordprocessingMLPackage exportWordByDoc4j(String basePath, ViewFormatItemInformation info, List<PageColumnConfigBean> colums,
    				String tagPrefix, String docTypeName, String docName) throws Exception{
    		//创建文档
    		Docx4jWord word = Docx4jWord.createWord();
    
    		//写标题
    		word.addParagraph(docTypeName + "-详细信息", true, 34, true);
    		word.addParagraph("所属文档《" + docName + "》", true, 22, false);
    
    		//读内容
    		String colName = "";
    		List<List<PageColumnConfigBean>> content = new ArrayList<>();//记录栏目内属性
    		List<String> columNames = new ArrayList<>();//记录栏目
    		for (int i = 0; i < colums.size(); i++) {
    			PageColumnConfigBean colum = colums.get(i);
    			//栏目
    			if (colum.getPojoName() == null && colum.getTitle() != null) {
    				colName = colum.getTitle();
    				columNames.add(colName);
    				List<PageColumnConfigBean> list = new ArrayList<>();
    				content.add(list);
    			} else {//属性
    				List<PageColumnConfigBean> list = content.get(content.size() - 1);
    				list.add(colum);
    			}
    		}
    
    		for (int i = 0; i < columNames.size(); i++) {
    			//写栏目
    			word.createTitleColumn(columNames.get(i));
    			//写栏目属性
    			if (content.get(i).size() > 0) {
    				List<String[]> table = getTableValuesByColums( content.get(i), info, tagPrefix);
    				word.createNormalTable(table, basePath);
    			}
    		}
    		return word.getWordMLPackage();
    	}
    

    特殊字符声明头:

    <!ENTITY iexcl "¡"><!ENTITY cent "¢"><!ENTITY pound "£"><!ENTITY curren "¤"><!ENTITY yen "¥"><!ENTITY brvbar "¦"><!ENTITY sect "§"><!ENTITY uml "¨"><!ENTITY copy "©"><!ENTITY ordf "ª"><!ENTITY laquo "«"><!ENTITY not "¬"><!ENTITY shy "­"><!ENTITY reg "®"><!ENTITY macr "¯"><!ENTITY deg "°"><!ENTITY plusmn "±"><!ENTITY sup2 "²"><!ENTITY sup3 "³"><!ENTITY acute "´"><!ENTITY micro "µ"><!ENTITY para "¶"><!ENTITY middot "·"><!ENTITY cedil "¸"><!ENTITY sup1 "¹"><!ENTITY ordm "º"><!ENTITY raquo "»"><!ENTITY frac14 "¼"><!ENTITY frac12 "½"><!ENTITY frac34 "¾"><!ENTITY iquest "¿"><!ENTITY Agrave "À"><!ENTITY Aacute "Á"><!ENTITY Acirc "Â"><!ENTITY Atilde "Ã"><!ENTITY Auml "Ä"><!ENTITY Aring "Å"><!ENTITY AElig "Æ"><!ENTITY Ccedil "Ç"><!ENTITY Egrave "È"><!ENTITY Eacute "É"><!ENTITY Ecirc "Ê"><!ENTITY Euml "Ë"><!ENTITY Igrave "Ì"><!ENTITY Iacute "Í"><!ENTITY Icirc "Î"><!ENTITY Iuml "Ï"><!ENTITY ETH "Ð"><!ENTITY Ntilde "Ñ"><!ENTITY Ograve "Ò"><!ENTITY Oacute "Ó"><!ENTITY Ocirc "Ô"><!ENTITY Otilde "Õ"><!ENTITY Ouml "Ö"><!ENTITY times "×"><!ENTITY Oslash "Ø"><!ENTITY Ugrave "Ù"><!ENTITY Uacute "Ú"><!ENTITY Ucirc "Û"><!ENTITY Uuml "Ü"><!ENTITY Yacute "Ý"><!ENTITY THORN "Þ"><!ENTITY szlig "ß"><!ENTITY agrave "à"><!ENTITY aacute "á"><!ENTITY acirc "â"><!ENTITY atilde "ã"><!ENTITY auml "ä"><!ENTITY aring "å"><!ENTITY aelig "æ"><!ENTITY ccedil "ç"><!ENTITY egrave "è"><!ENTITY eacute "é"><!ENTITY ecirc "ê"><!ENTITY euml "ë"><!ENTITY igrave "ì"><!ENTITY iacute "í"><!ENTITY icirc "î"><!ENTITY iuml "ï"><!ENTITY eth "ð"><!ENTITY ntilde "ñ"><!ENTITY ograve "ò"><!ENTITY oacute "ó"><!ENTITY ocirc "ô"><!ENTITY otilde "õ"><!ENTITY ouml "ö"><!ENTITY divide "÷"><!ENTITY oslash "ø"><!ENTITY ugrave "ù"><!ENTITY uacute "ú"><!ENTITY ucirc "û"><!ENTITY uuml "ü"><!ENTITY yacute "ý"><!ENTITY thorn "þ"><!ENTITY yuml "ÿ"><!ENTITY fnof "ƒ"><!ENTITY Alpha "Α"><!ENTITY Beta "Β"><!ENTITY Gamma "Γ"><!ENTITY Delta "Δ"><!ENTITY Epsilon "Ε"><!ENTITY Zeta "Ζ"><!ENTITY Eta "Η"><!ENTITY Theta "Θ"><!ENTITY Iota "Ι"><!ENTITY Kappa "Κ"><!ENTITY Lambda "Λ"><!ENTITY Mu "Μ"><!ENTITY Nu "Ν"><!ENTITY Xi "Ξ"><!ENTITY Omicron "Ο"><!ENTITY Pi "Π"><!ENTITY Rho "Ρ"><!ENTITY Sigma "Σ"><!ENTITY Tau "Τ"><!ENTITY Upsilon "Υ"><!ENTITY Phi "Φ"><!ENTITY Chi "Χ"><!ENTITY Psi "Ψ"><!ENTITY Omega "Ω"><!ENTITY alpha "α"><!ENTITY beta "β"><!ENTITY gamma "γ"><!ENTITY delta "δ"><!ENTITY epsilon "ε"><!ENTITY zeta "ζ"><!ENTITY eta "η"><!ENTITY theta "θ"><!ENTITY iota "ι"><!ENTITY kappa "κ"><!ENTITY lambda "λ"><!ENTITY mu "μ"><!ENTITY nu "ν"><!ENTITY xi "ξ"><!ENTITY omicron "ο"><!ENTITY pi "π"><!ENTITY rho "ρ"><!ENTITY sigmaf "ς"><!ENTITY sigma "σ"><!ENTITY tau "τ"><!ENTITY upsilon "υ"><!ENTITY phi "φ"><!ENTITY chi "χ"><!ENTITY psi "ψ"><!ENTITY omega "ω"><!ENTITY thetasym "ϑ"><!ENTITY upsih "ϒ"><!ENTITY piv "ϖ"><!ENTITY bull "•"><!ENTITY hellip "…"><!ENTITY prime "′"><!ENTITY Prime "″"><!ENTITY oline "‾"><!ENTITY frasl "⁄"><!ENTITY weierp "℘"><!ENTITY image "ℑ"><!ENTITY real "ℜ"><!ENTITY trade "™"><!ENTITY alefsym "ℵ"><!ENTITY larr "←"><!ENTITY uarr "↑"><!ENTITY rarr "→"><!ENTITY darr "↓"><!ENTITY harr "↔"><!ENTITY crarr "↵"><!ENTITY lArr "⇐"><!ENTITY uArr "⇑"><!ENTITY rArr "⇒"><!ENTITY dArr "⇓"><!ENTITY hArr "⇔"><!ENTITY forall "∀"><!ENTITY part "∂"><!ENTITY exist "∃"><!ENTITY empty "∅"><!ENTITY nabla "∇"><!ENTITY isin "∈"><!ENTITY notin "∉"><!ENTITY ni "∋"><!ENTITY prod "∏"><!ENTITY sum "∑"><!ENTITY minus "−"><!ENTITY lowast "∗"><!ENTITY radic "√"><!ENTITY prop "∝"><!ENTITY infin "∞"><!ENTITY ang "∠"><!ENTITY and "∧"><!ENTITY or "∨"><!ENTITY cap "∩"><!ENTITY cup "∪"><!ENTITY int "∫"><!ENTITY there4 "∴"><!ENTITY sim "∼"><!ENTITY cong "≅"><!ENTITY asymp "≈"><!ENTITY ne "≠"><!ENTITY equiv "≡"><!ENTITY le "≤"><!ENTITY ge "≥"><!ENTITY sub "⊂"><!ENTITY sup "⊃"><!ENTITY nsub "⊄"><!ENTITY sube "⊆"><!ENTITY supe "⊇"><!ENTITY oplus "⊕"><!ENTITY otimes "⊗"><!ENTITY perp "⊥"><!ENTITY sdot "⋅"><!ENTITY lceil "⌈"><!ENTITY rceil "⌉"><!ENTITY lfloor "⌊"><!ENTITY rfloor "⌋"><!ENTITY lang "〈"><!ENTITY rang "〉"><!ENTITY loz "◊"><!ENTITY spades "♠"><!ENTITY clubs "♣"><!ENTITY hearts "♥"><!ENTITY diams "♦"><!ENTITY quot """><!ENTITY amp "&"><!ENTITY lt "<"><!ENTITY gt ">"><!ENTITY OElig "Œ"><!ENTITY oelig "œ"><!ENTITY Scaron "Š"><!ENTITY scaron "š"><!ENTITY Yuml "Ÿ"><!ENTITY circ "ˆ"><!ENTITY tilde "˜"><!ENTITY ensp " "><!ENTITY emsp " "><!ENTITY thinsp " "><!ENTITY zwnj "‌"><!ENTITY zwj "‍"><!ENTITY lrm "‎"><!ENTITY rlm "‏"><!ENTITY ndash "–"><!ENTITY mdash "—"><!ENTITY lsquo "‘"><!ENTITY rsquo "’"><!ENTITY sbquo "‚"><!ENTITY ldquo "“"><!ENTITY rdquo "”"><!ENTITY bdquo "„"><!ENTITY dagger "†"><!ENTITY Dagger "‡"><!ENTITY permil "‰"><!ENTITY lsaquo "‹"><!ENTITY rsaquo "›"><!ENTITY euro "€">

    ]>

    展开全文
    weixin_43328682 2019-09-20 16:02:50
  • 前两天遇到docx4j导出word文档的时候,系统卡死,需要重启服务才能正常运行。环境是:windowsjdk1.7eclipse+tomcat后台打印日志如下:七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context &lt;clinit&gt; ...

    前两天遇到docx4j导出word文档的时候,系统卡死,需要重启服务才能正常运行。

    环境是:

    windows

    jdk1.7

    eclipse+tomcat

    后台打印日志如下:

    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context <clinit>
    信息: java.vendor=Oracle Corporation
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context <clinit>
    信息: java.version=1.7.0_79
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: 
    jar:file:/F:/application/wyqh/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/tbp-web-app/WEB-INF/lib/jaxb-impl-2.1.12.jar!/META-INF/MANIFEST.MF
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Implementation-Title : JAXB Reference Implementation 
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Implementation-Version : 2.1.12
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Class-Path : jaxb-api.jar activation.jar jsr173_1.0_api.jar jaxb1-impl.jar
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Manifest-Version : 1.0
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Specification-Vendor : Sun Microsystems, Inc.
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Created-By : 1.5.0_12-b04 (Sun Microsystems Inc.)
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Ant-Version : Apache Ant 1.7.0
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Implementation-Vendor : Sun Microsystems, Inc.
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Implementation-Vendor-Id : com.sun
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Specification-Title : Java Architecture for XML Binding
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Specification-Version : 2.1
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Extension-Name : com.sun.xml.bind
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Build-Id : hudson-jaxb-ri-2.1-833
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Found JAXB reference implementation in jar:file:/F:/application/wyqh/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/tbp-web-app/WEB-INF/lib/jaxb-impl-2.1.12.jar!/META-INF/MANIFEST.MF
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Implementation-Version : hudson-jaxb-ri-2.1-833
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: 
    jar:file:/F:/application/wyqh/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/tbp-web-app/WEB-INF/lib/jaxb-xjc-2.2.1.1.jar!/META-INF/MANIFEST.MF
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Implementation-Title : JAXB Reference Implementation 
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Implementation-Version : 2.2.2
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Class-Path : jaxb-api.jar jaxb-impl.jar jsr173_1.0_api.jar activation.jar
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Manifest-Version : 1.0
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Specification-Vendor : Sun Microsystems, Inc.
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Created-By : 1.5.0_20-b02 (Sun Microsystems Inc.)
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Ant-Version : Apache Ant 1.7.1
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Implementation-Vendor : Sun Microsystems, Inc.
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Implementation-Vendor-Id : com.sun
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Specification-Title : Java Architecture for XML Binding
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Specification-Version : 2.2.1
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Main-Class : com.sun.tools.xjc.XJCFacade
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Extension-Name : com.sun.tools.xjc
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.Context searchManifestsForJAXBImplementationInfo
    信息: Build-Id : hudson-jaxb-ri-2.2-27
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.NamespacePrefixMapperUtils getPrefixMapper
    警告: name: com.sun.xml.internal.bind.namespacePrefixMapper value: org.docx4j.jaxb.NamespacePrefixMapperSunInternal@619f4d36 .. trying RI.
    七月 05, 2018 10:57:15 上午 org.docx4j.jaxb.NamespacePrefixMapperUtils tryUsingRI
    信息: Using NamespacePrefixMapper, which is suitable for the JAXB RI
    
    

    开始的时候 以为是JAXB有问题,在Stack Overflow上也没有找到想要的答案,后来想到可能是JVM内存不够,于是就加了参数


    在eclipse中配置:



    参数:-Xms512m -Xmx1024m -XX:PermSize=256M -XX:MaxPermSize=256M

    问题解决。

    展开全文
    d_holyDancer 2018-07-05 11:02:45
  • 最近公司让我实现一个利用原有word模板,导出word文档的功能模块,发现docx4j是个很不错的工具,但是之前从来没有用过,对此并不了解,于是上网查找相关资料,也是非常少之,于是便自己开始摸索。1、原有word模板...

    最近公司让我实现一个利用原有word模板,导出word文档的功能模块,发现docx4j是个很不错的工具,但是之前从来没有用过,对此并不了解,于是上网查找相关资料,也是非常少之,于是便自己开始摸索。

    1、原有word模板内容如下:

    2、在想要插入数据的地方,插入书签,之后会在代码中获取书签并遍历插入内容。


    3、直接上代码。

    (1)首先我将word模板文件路径配置在config.properties文件中

    soil_word_template=/template/soil-report.docx
    soil_word_filename=soil-report.docx
    (2)然后是controller层
    /**
    	 * 根据表名统计土壤墒情数据并导出word文档
    	 * 
    	 * @param table
    	 *            表名
    	 * @param cropDate
    	 *            监测日期
    	 * @param file
    	 *            BASE64编码的图片文件
    	 * @param request
    	 * @param response
    	 * @return
    	 */
    	@ApiOperation("根据表名统计土壤墒情数据并导出word文档")
    	@RequestMapping(value = "/exportWordReport", method = RequestMethod.POST)
    	@ApiImplicitParams({ @ApiImplicitParam(name = "table", value = "表名",required=false,dataType="query"), @ApiImplicitParam(name="cropDate",value="监测日期",required=false,dataType="query"),
    		@ApiImplicitParam(name = "file", value = "BASE64编码的图片字符",required=false,dataType="query")})
    	public void exportWordReport(String table, String cropDate, String file, HttpServletRequest request,
    			HttpServletResponse response) {
    		// soil_word_template=/template/soil-report.docx
    		// soil_word_filename=soil-report.docx
    		ServletOutputStream out = null;
    		InputStream in = null;
    		File resultFile = null;
    		try {
    			// 土壤墒情word文档模板路径
    			String path = request.getServletContext().getRealPath("") + PropertyUtil.get("soil_word_template");
    			String tempPath = request.getServletContext().getRealPath("");
    			WordprocessingMLPackage wPackage = soilService.exportWordReport(table, cropDate, file, path);
    			// 设置文件属性
    			// wPackage.save(new File("C:\\Users\\admin\\Desktop\\" +
    			// PropertyUtil.get("soil_word_filename")));
    			String fileName = PropertyUtil.get("soil_word_filename");
    			String msg = new String((fileName).getBytes("UTF-8"), "ISO8859-1");
    			response.setContentType("application/msword");
    			response.addHeader("Content-Disposition", "attachment;filename=" + msg);
    
    			// response.setContentType("application/octet-stream");
    			// response.setContentType("application/vnd.ms-excel");
    			response.setCharacterEncoding("UTF-8");
    			// response.addHeader("result", "ok");
    			// response.setContentType("multipart/form-data");
    			out = response.getOutputStream();
    			String strDate = DateUtil.date2String(new Date(), DateUtil.DATE_FORMAT2);
    			resultFile = new File(tempPath + "/tempfile", "soil-report(" + strDate + ").docx");
    			wPackage.save(resultFile);
    			in = new FileInputStream(resultFile);
    			byte[] buffer = new byte[1024];
    			int len = 0;
    			while ((len = in.read(buffer)) > 0) {
    				out.write(buffer, 0, len);
    			}
    			// wPackage.save(out);
    			// wPackage.save(new File("C:\\Users\\admin\\Desktop\\",
    			// "dddd1111.docx"));
    		} catch (Exception e) {
    			Log.error(e);
    		} finally {
    			try {
    				if (out != null) {
    					out.flush();
    					out.close();
    				}
    				if (in != null) {
    					in.close();
    					if (resultFile != null && resultFile.exists() && resultFile.isFile()) {
    						resultFile.delete();
    					}
    				}
    			} catch (IOException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    	}

    controller 层中需要注意的地方的是,最开始我用

    wPackage.save(out);//直接输出到response的ServletOutPutStream流中,但是这种方式会报错,好像是socket异常之类的问题。

    后来改成了代码中的方式,先将文件导出到项目src的webapp文件夹的tempfile文件夹中,然后再从此文件夹中读取该文件,并用out.write()方式输出便能成功执行导出word,前端紧接着下载该word即可。

                            int len = 0;
    			while ((len = in.read(buffer)) > 0) {
    				out.write(buffer, 0, len);
    			}

    (3)service层以及serviceImpl层代码

    首先来看看咱们需要

    是SoilService层代码:

    	/**SoilService层
    	 * 根据表名进行统计并导出word报告文档
    	 * 
    	 * @param tableName 表名
    	 * @param cropDate 监测日期
    	 * @param file  base64编码的图片文件字符串
    	 * @param path  word模板文件路径
    	 * @return Map<String, Object>
    	 */
    	WordprocessingMLPackage exportWordReport(String tableName, String cropDate, String file, String path);

    然后贴上SoilServiceImpl代码:

    	/**
    	 * 根据表名进行统计并导出word报告文档
    	 * 
    	 * @param tableName
    	 * @param where
    	 * @param file
    	 * @return Map<String, Object>
    	 */
    	@Override
    	public WordprocessingMLPackage exportWordReport(String tableName, String cropDate, String file, String path) {
    		// TODO Auto-generated method stub
    
    		Map<String, Object> resultMap = new HashMap<String, Object>();
    		// DecimalFormat decimalFormat = new DecimalFormat("0.00");
    		// 此处可能添加过滤非监测区的条件
    		String where = " \"GRIDCODE\"<8 ";
    		resultMap = findStatisticsDateByTableName(tableName, where);
    		JSONArray jsonArray = (JSONArray) resultMap.get("data1");
    		double totalArea = 0.0; // 有效监测区面积
    		double tooMuchArea = 0.0; // 过多面积1
    		double suitableArea = 0.0;// 适宜面积2
    		double notEnoughArea = 0.0;// 不足面积3
    		double lightDroughtArea = 0.0;// 轻旱面积4
    		double middleDroughtArea = 0.0;// 中旱面积5
    		double heavyDroughtArea = 0.0;// 重旱面积6
    		double extremeDroughtArea = 0.0;// 极旱面积7
    		// double notMonitorArea =0.0; //非监测区8
    
    		double tooMuchRate = 0.0; // 过多面积占比1
    		double suitableRate = 0.0;// 适宜面积2
    		double notEnoughRate = 0.0;// 不足面积3
    		double lightDroughtRate = 0.0;// 轻旱面积4
    		double middleDroughtRate = 0.0;// 中旱面积5
    		double heavyDroughtRate = 0.0;// 重旱面积6
    		double extremeDroughtRate = 0.0;// 极旱面积7
    		// double notMonitorRate =0.0; //非监测区8
    
    		for (Object obj : jsonArray) {
    			JSONObject jsonObject = (JSONObject) obj;
    			String gridcode = jsonObject.getString("gridcode");
    			double area = jsonObject.getDoubleValue("area");
    			if ("1".equals(gridcode)) {
    				tooMuchArea = area * Constant.I;
    			} else if ("2".equals(gridcode)) {
    				suitableArea = area * Constant.I;
    			} else if ("3".equals(gridcode)) {
    				notEnoughArea = area * Constant.I;
    			} else if ("4".equals(gridcode)) {
    				lightDroughtArea = area * Constant.I;
    			} else if ("5".equals(gridcode)) {
    				middleDroughtArea = area * Constant.I;
    			} else if ("6".equals(gridcode)) {
    				heavyDroughtArea = area * Constant.I;
    			} else if ("7".equals(gridcode)) {
    				extremeDroughtArea = area * Constant.I;
    			}
    			// }else if("8".equals(gridcode)){
    			// notMonitorArea =area;
    			// }
    			totalArea += area * Constant.I;
    		}
    		if (totalArea != 0.0) {
    			tooMuchRate = Double.valueOf(DECIMAL_FORMAT.format((tooMuchArea / totalArea) * 100));
    			suitableRate = Double.valueOf(DECIMAL_FORMAT.format((suitableArea / totalArea) * 100));
    			notEnoughRate = Double.valueOf(DECIMAL_FORMAT.format((notEnoughArea / totalArea) * 100));
    			lightDroughtRate = Double.valueOf(DECIMAL_FORMAT.format((lightDroughtArea / totalArea) * 100));
    			middleDroughtRate = Double.valueOf(DECIMAL_FORMAT.format((middleDroughtArea / totalArea) * 100));
    			heavyDroughtRate = Double.valueOf(DECIMAL_FORMAT.format((heavyDroughtArea / totalArea) * 100));
    			extremeDroughtRate = Double.valueOf(DECIMAL_FORMAT.format((extremeDroughtArea / totalArea) * 100));
    		}
    		Map<String, Object> map = new HashMap<String, Object>();
    
    		map.put("cropDate", cropDate);
    		map.put("totalArea", DECIMAL_FORMAT.format(totalArea));
    		map.put("mTotalArea", DECIMAL_FORMAT.format(totalArea / Constant.I * Constant.M));
    		map.put("tooMuchArea", DECIMAL_FORMAT.format(tooMuchArea));
    		map.put("suitableArea", DECIMAL_FORMAT.format(suitableArea));
    		map.put("notEnoughArea", DECIMAL_FORMAT.format(notEnoughArea));
    		map.put("lightDroughtArea", DECIMAL_FORMAT.format(lightDroughtArea)); 
    		map.put("middleDroughtArea", DECIMAL_FORMAT.format(middleDroughtArea));
    		map.put("heavyDroughtArea", DECIMAL_FORMAT.format(heavyDroughtArea));
    		map.put("extremeDroughtArea", DECIMAL_FORMAT.format(extremeDroughtArea));
    		
    		map.put("tooMuchAreaM", DECIMAL_FORMAT.format(tooMuchArea/ Constant.I * Constant.M));
    		map.put("suitableAreaM", DECIMAL_FORMAT.format(suitableArea/ Constant.I * Constant.M));
    		map.put("notEnoughAreaM", DECIMAL_FORMAT.format(notEnoughArea/ Constant.I * Constant.M));
    		map.put("lightDroughtAreaM", DECIMAL_FORMAT.format(lightDroughtArea/ Constant.I * Constant.M)); 
    		map.put("middleDroughtAreaM", DECIMAL_FORMAT.format(middleDroughtArea/ Constant.I * Constant.M));
    		map.put("heavyDroughtAreaM", DECIMAL_FORMAT.format(heavyDroughtArea/ Constant.I * Constant.M));
    		map.put("extremeDroughtAreaM", DECIMAL_FORMAT.format(extremeDroughtArea/ Constant.I * Constant.M));
    
    		map.put("tooMuchRate", tooMuchRate);
    		map.put("suitableRate", suitableRate);
    		map.put("notEnoughRate", notEnoughRate);
    		map.put("lightDroughtRate", lightDroughtRate);
    		map.put("middleDroughtRate", middleDroughtRate);
    		map.put("heavyDroughtRate", heavyDroughtRate);
    		map.put("extremeDroughtRate", extremeDroughtRate);
    
    		String sql = "SELECT *  from (SELECT \"PROVINCE\",\"CITY\",\"COUNTY\",\"TOWN\",\"CROPTYPE\",\"GRIDCODE\",SUM(\"AREA\") \"AREA\"  FROM \""
    				+ tableName
    				+ "\" WHERE \"GRIDCODE\"<8 AND \"GRIDCODE\"  IS NOT NULL group by \"PROVINCE\",\"CITY\",\"COUNTY\",\"TOWN\",\"CROPTYPE\",\"GRIDCODE\") A "
    				+ "WHERE A.\"AREA\"!=0 AND A.\"AREA\" IS NOT NULL";
    		String totalAreaSql = "SELECT SUM(\"AREA\") \"TOTALAREA\"  from (SELECT \"PROVINCE\",\"CITY\",\"COUNTY\",\"TOWN\",\"CROPTYPE\",\"GRIDCODE\",SUM(\"AREA\") \"AREA\"  FROM \""
    				+ tableName
    				+ "\" WHERE \"GRIDCODE\"<8 AND \"GRIDCODE\"  IS NOT NULL group by \"PROVINCE\",\"CITY\",\"COUNTY\",\"TOWN\",\"CROPTYPE\",\"GRIDCODE\") A "
    				+ "WHERE A.\"AREA\"!=0 AND A.\"AREA\" IS NOT NULL";
    		List<Object[]> list = getBySql(sql, null);
    		double soilTotalArea = Double.valueOf(Objects.toString(getBySql(totalAreaSql, null).get(0), "0.0"))
    				* Constant.M;
    		List<SoilDtoEntityRate> soilList = list.parallelStream().map(x -> coverProperty(x, soilTotalArea))
    				.collect(Collectors.toList());
    		map.put("table", soilList);
    		// map.put("soilTotalArea", soilTotalArea);
    		map.put("img", file);
    		try {
    			WordprocessingMLPackage wPackage = WordprocessingMLPackage.load(new FileInputStream(path));
    			replaceContentByBookmark(wPackage, map);
    			// wPackage.save(new File("C:\\Users\\admin\\Desktop\\" +
    			// PropertyUtil.get("soil_word_filename")));
    			return wPackage;
    		} catch (FileNotFoundException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (Docx4JException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		return null;
    	}
    /**
    	 * 根据多个标签替换段落中的内容
    	 * 
    	 * @param map
    	 */
    	public void replaceContentByBookmark(WordprocessingMLPackage wPackage, Map<String, Object> map) {
    		// 载入模板文件
    		try {
    			// 提取正文
    			MainDocumentPart main = wPackage.getMainDocumentPart();
    			Document doc = main.getContents();
    			Body body = doc.getBody();
    			// ObjectFactory factory = Context.getWmlObjectFactory();
    			// 获取段落
    			List<Object> paragraphs = body.getContent();
    			// 提取书签并创建书签的游标
    			RangeFinder rt = new RangeFinder("CTBookmark", "CTMarkupRange");
    			new TraversalUtil(paragraphs, rt);
    
    			// 遍历书签(在书签处插入文本内容和书签)
    			for (CTBookmark bm : rt.getStarts()) {
    				// 这儿可以对单个书签进行操作,也可以用一个map对所有的书签进行处理
    				if (!bm.getName().equals(DocUtil.tableName)) {
    					if (bm.getName().equals(DocUtil.imageBookMarkName)) { // 图片
    						String file = (String) map.get(bm.getName());
    						if (StringUtils.isNotBlank(file)) {
    							// InputStream inputStream =file.getInputStream();
    							DocUtil.addImage(wPackage, bm, file);
    						}
    					} else {
    						DocUtil.replaceText(bm, map.get(bm.getName()));
    					}
    				} else { // 表格
    					List<SoilDtoEntityRate> list = (List<SoilDtoEntityRate>) map.get(bm.getName());
    					// 创建表格
    					int rowIndex = 2; // 从第三行开始写起(表格从0开始)
    					Tbl tbl = Doc4JUtil.createTable(wPackage, list.size() + rowIndex, 6);
    					Doc4JUtil.mergeCellsHorizontal(tbl, 0, 0, 5);
    					// 设置表格大标题
    					P p = Doc4JUtil.createP("农作物墒情统计列表", "36");
    					Doc4JUtil.setTcValue(tbl, 0, 0, p);
    					// 设置表格副标题
    					Doc4JUtil.setTcValue(tbl, 1, 0, "县区");
    					Doc4JUtil.setTcValue(tbl, 1, 1, "乡镇");
    					Doc4JUtil.setTcValue(tbl, 1, 2, "作物");
    					Doc4JUtil.setTcValue(tbl, 1, 3, "墒情等级");
    					Doc4JUtil.setTcValue(tbl, 1, 4, "面积(亩)");
    					Doc4JUtil.setTcValue(tbl, 1, 5, "占比");
    
    					Map<String, List<SoilDtoEntityRate>> provinceCollect = list.stream()
    							.collect(Collectors.groupingBy(x -> x.getProvince() == null ? "" : x.getProvince()));
    
    					for (Entry<String, List<SoilDtoEntityRate>> proEntry : provinceCollect.entrySet()) {
    
    						Map<String, List<SoilDtoEntityRate>> cityCollect = proEntry.getValue().stream()
    								.collect(Collectors.groupingBy(x -> x.getCity() == null ? "" : x.getCity()));
    						for (Entry<String, List<SoilDtoEntityRate>> cityEntry : cityCollect.entrySet()) {
    							Map<String, List<SoilDtoEntityRate>> countyCollect = cityEntry.getValue().stream()
    									.collect(Collectors.groupingBy(x -> x.getCounty() == null ? "" : x.getCounty()));
    
    							for (Entry<String, List<SoilDtoEntityRate>> countyEntry : countyCollect.entrySet()) {
    								operateCounty(countyEntry, rowIndex, tbl);
    								rowIndex += countyEntry.getValue().size();
    							}
    
    						}
    
    					}
    					Doc4JUtil.setTblAllJcAlign(tbl, JcEnumeration.CENTER);
    					Doc4JUtil.setTblAllVAlign(tbl, STVerticalJc.CENTER);
    					wPackage.getMainDocumentPart().addObject(tbl);
    				}
    			}
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    
    	/**
    	 * 写入县区数据
    	 * 
    	 * @param countyEntry
    	 * @param rowIndex
    	 * @param tbl
    	 */
    	private void operateCounty(Entry<String, List<SoilDtoEntityRate>> countyEntry, int rowIndex, Tbl tbl) {
    		// TODO Auto-generated method stub
    		// 获取每个entry的记录条数
    		int beginRow = rowIndex;
    		int size = countyEntry.getValue().size();
    		// 处理县区
    		// 合并单元格
    		Doc4JUtil.mergeCellsVertically(tbl, 0, beginRow, beginRow + size);
    		Doc4JUtil.setTcValue(tbl, beginRow, 0, countyEntry.getKey());
    		// 处理镇
    		Map<String, List<SoilDtoEntityRate>> townCollect = countyEntry.getValue().stream()
    				.collect(Collectors.groupingBy(x -> x.getTown() == null ? "" : x.getTown()));
    		for (Entry<String, List<SoilDtoEntityRate>> townEntry : townCollect.entrySet()) {
    			operateTown(townEntry, beginRow, tbl);
    			beginRow += townEntry.getValue().size();
    		}
    	}
    
    	/**
    	 * 写入镇数据
    	 * 
    	 * @param townEntry
    	 * @param rowIndex
    	 * @param tbl
    	 */
    	private void operateTown(Entry<String, List<SoilDtoEntityRate>> townEntry, int rowIndex, Tbl tbl) {
    		// TODO Auto-generated method stub
    		// 获取每个entry的记录条数
    		int beginRow = rowIndex;
    		int size = townEntry.getValue().size();
    		// 处理县区
    		// 合并单元格
    		Doc4JUtil.mergeCellsVertically(tbl, 1, beginRow, beginRow + size);
    		Doc4JUtil.setTcValue(tbl, beginRow, 1, townEntry.getKey());
    		Map<String, List<SoilDtoEntityRate>> cropCollect = townEntry.getValue().stream().sorted((x, j) -> {
    			return (int) (x.getGridcode() - j.getGridcode());
    		}).collect(Collectors.groupingBy(x -> x.getCroptype() == null ? "" : x.getCroptype()));
    		for (Entry<String, List<SoilDtoEntityRate>> cropEntry : cropCollect.entrySet()) {
    			operateCropType(cropEntry, beginRow, tbl);
    			beginRow += cropEntry.getValue().size();
    		}
    
    	}
    
    	/**
    	 * 写入种植类型、土壤墒情等级,面积,占比
    	 * 
    	 * @param cropEntry
    	 * @param rowIndex
    	 * @param tbl
    	 */
    	private void operateCropType(Entry<String, List<SoilDtoEntityRate>> cropEntry, int rowIndex, Tbl tbl) {
    		// TODO Auto-generated method stub
    
    		int beginRow = rowIndex;
    		int size = cropEntry.getValue().size();
    		// 处理县区
    		// 合并单元格
    		Doc4JUtil.mergeCellsVertically(tbl, 2, beginRow, beginRow + size);
    		Doc4JUtil.setTcValue(tbl, beginRow, 2, cropEntry.getKey());
    		List<SoilDtoEntityRate> soilList = cropEntry.getValue();
    		for (int i = 0; i < size; i++) {
    			Doc4JUtil.setTcValue(tbl, beginRow + i, 3, gridCodeMap.get(soilList.get(i).getGridcode()));
    			Doc4JUtil.setTcValue(tbl, beginRow + i, 4, String.valueOf(soilList.get(i).getArea()));
    			Doc4JUtil.setTcValue(tbl, beginRow + i, 5, soilList.get(i).getRate());
    		}
    	}
    public SoilDtoEntityRate coverProperty(Object[] x, double totalSoilArea) {
    		String rate = "0.00%";
    		double area = Double.valueOf(Objects.toString(x[6], "0")) * Constant.M;
    		area = Double.valueOf(DECIMAL_FORMAT.format(area));
    		if (totalSoilArea != 0) {
    			rate = DECIMAL_FORMAT.format((area / totalSoilArea) * 100) + "%";
    		}
    		return new SoilDtoEntityRate(Objects.toString(x[0], ""), Objects.toString(x[1], ""), Objects.toString(x[2], ""),
    				Objects.toString(x[3], ""), Objects.toString(x[4], ""), Double.valueOf(Objects.toString(x[5], "0")),
    				area, rate);
    	}

    接下来是以上业务代码中用到的工具类中的方法:

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

    至此,大家就可以看到导出的word文档效果了,如下图:


    最后,大家在遇到此类问题的时候也可参考本篇博客,同时本人初次发表博客,时间仓促,尚且还有不妥之处,欢迎指正!

    展开全文
    qq_31905135 2018-05-24 14:17:32
  • 37.8MB u011144617 2019-12-31 16:48:51
  • public static <T> void getDocx(String fileName, List<Map<String, Object>> List) throws Exception { ... String testPath = "docx/研究生导师信息详细导出.docx"; //输出...
        public static <T> void getDocx(String fileName, List<Map<String, Object>> List) throws Exception {
            //模板路径
            String testPath = "docx/导出.docx";
            //输出路径1
            String outPath = "D:/1/"+fileName+".docx";
            //书签名称
            String bookmarkName = "bookmark";
            // 图片路径
            String imagePath = "C:\\Users\\Administrator\\Desktop\\1.jpg";
            
            WordprocessingMLPackage wordMlPackage = WordprocessingMLPackage.load(Thread.currentThread().getContextClassLoader().getResourceAsStream(testPath));;
            org.docx4j.finders.ClassFinder find = new ClassFinder(Tbl.class);
            new TraversalUtil(wordMlPackage.getMainDocumentPart().getContent(),find);
    
    
            // 提取正文
            MainDocumentPart mainDocumentPart = wordMlPackage.getMainDocumentPart();
            Document wmlDoc = (Document) mainDocumentPart.getJaxbElement();
            Body body = wmlDoc.getBody();
            // 提取正文中所有段落
            List<Object> paragraphs = body.getContent();
            // 提取书签并创建书签的游标
            RangeFinder rt = new RangeFinder("CTBookmark", "CTMarkupRange");
            new TraversalUtil(paragraphs, rt);
    
    
            //构造循环列表的数据
            Map<String, String> mappings = null;
    
            List wordInformationDataList = null;
            for (Map<String,Object> data:List
            ) {
                String type = (String) data.get("type");
                
                //如果type为1,,则设置为全局变量
                if ("1".equals(type)) {
                    List datalist = (List) data.get("datalist");
                      mappings = (HashMap<String, String>) datalist.get(0);
                      mappings = mapSetNullToBlankString(mappings);
                } else {
                    wordInformationDataList = (List) data.get("datalist");
                    //读取第几个表格
                    Tbl table = (Tbl) find.results.get(Integer.valueOf(type)-1);
    //        获取模板行的XML数据
                    Tr dynamicTr = (Tr) table.getContent().get(1);
                    String dynamicTrXml = XmlUtils.marshaltoString(dynamicTr);
                    List<Map<String,Object>> dataList= new ArrayList<Map<String, Object>>() ;
                    dataList = wordInformationDataList;
                    for (Map<String,Object> dataMap :dataList){
                        Map map = mapSetNullToBlankString(dataMap);
                        Tr newTr = (Tr)XmlUtils.unmarshallFromTemplate(dynamicTrXml,map);
                        table.getContent().add(newTr);
                    }
                    //删除模板行的站位行
                    table.getContent().remove(1);
                }
    
    
            }
    
            // 遍历书签
            for (CTBookmark bm:rt.getStarts()) {
                // 这儿可以对单个书签进行操作,也可以用一个map对所有的书签进行处理
                if (bm.getName().equals(bookmarkName)){
                    // 读入图片并转化为字节数组,因为docx4j只能字节数组的方式插入图片
                    InputStream is = new FileInputStream(imagePath);
                    byte[] bytes = IOUtils.toByteArray(is);
                    // 穿件一个行内图片
                    BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wordMlPackage, bytes);
    
                    // createImageInline函数的前四个参数我都没有找到具体啥意思,,,,
                    // 最有一个是限制图片的宽度,缩放的依据
                    Inline inline = imagePart.createImageInline(null, null, 0,1, false, 1800);
                    // 获取该书签的父级段落
                    P p = (P)(bm.getParent());
                    ObjectFactory factory = new ObjectFactory();
                    // R对象是匿名的复杂类型,然而我并不知道具体啥意思,估计这个要好好去看看ooxml才知道
                    R run = factory.createR();
                    // drawing理解为画布?
                    Drawing drawing = factory.createDrawing();
                    drawing.getAnchorOrInline().add(inline);
                    run.getContent().add(drawing);
                    p.getContent().add(run);
                }
            }
    
    
            //替换全局变量
            wordMlPackage.getMainDocumentPart().variableReplace(mappings);
            //输出文件
            Docx4J.save(wordMlPackage,new File(outPath));
    
    
    
        }
    mapSetNullToBlankString(Map map) 是将map中的null替换为空字符串的方法,docx4j使用模板导出时,如果值为null会在表格内留下字段名。
    展开全文
    u010942058 2020-03-10 22:13:20
  • weixin_42982636 2021-09-30 16:45:37
  • Gufengrong 2020-01-02 20:33:14
  • xiaosemei 2021-07-02 09:44:58
  • hunwanjie 2019-07-24 15:53:24
  • 12KB weixin_38669628 2019-08-07 02:11:56
  • qq_24378737 2021-05-11 11:30:29
  • xiaoping_fffcs 2017-11-06 07:32:44
  • dnc8371 2020-05-05 19:35:39
  • 11.33MB yybm909n 2020-05-16 09:31:31
  • chy555chy 2021-09-17 20:08:53
  • fanxiangru999 2018-08-24 22:08:19
  • qq_40429540 2020-10-26 17:26:22
  • lwl20140904 2017-06-16 09:53:14
  • tianyangwww 2014-01-23 14:51:08
  • XYmar 2020-06-15 16:56:39
  • zkqloveyu1314 2016-05-12 09:24:20
  • hhwygang 2017-05-12 15:16:12
  • 15.56MB qq_25170227 2019-06-05 18:54:16
  • 43.19MB qq_40856316 2020-07-19 22:47:27
  • 4KB u013480019 2020-06-12 16:57:03
  • u013604967 2015-05-05 17:26:13
  • u013014691 2019-10-25 12:14:40
  • HP1004 2019-11-21 15:05:36

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,203
精华内容 481
关键字:

docx4j导出word