DOC4J插入表格与HTML

2019-06-13  本文已影响0人  千叶鸟

请先阅读以下资料
https://www.baeldung.com/docx4j
官网
官方论坛(挺有用的,大部分问题在这里都能检索到)

开始

添加maven依赖

<!-- https://mvnrepository.com/artifact/org.docx4j/docx4j -->
<dependency>
    <groupId>org.docx4j</groupId>
    <artifactId>docx4j</artifactId>
    <version>6.0.1</version>
</dependency>

我这边引入的是6.0.1版本的docx4j,而且并没有额外引入jaxb-api,目前没有发现有什么影响

插入HTML

一些基础的操作在baeldung的资料中已经有了,我就不再提及了,这里主要说明下如何将html文本插入到word中。

在段落中插入Html

public void insertHtml() {
        //  构建一个html内容
        String content = "<p style=\"color:red\">一段HTML</p>";
        String htmlStr = "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html\"; charset=\"utf-8\"></head><body>" + content + "<p><br/></p></body></html>";
        
        WordprocessingMLPackage aPackage;
        try {
            //  创建一个临时文件
            File tempFile = File.createTempFile("test", ".docx");
            aPackage = WordprocessingMLPackage.createPackage();
            //  插入段落文本
            aPackage.getMainDocumentPart().addParagraphOfText("hello");
            //  插入HTML
            aPackage.getMainDocumentPart().addAltChunk(AltChunkType.Html, htmlStr.getBytes(Charsets.UTF_8));
            //  将构建的word内容保存到临时文件
            aPackage.save(tempFile);
        } catch (IOException | Docx4JException e) {
            e.printStackTrace();
        }
    }

结果:


image

在表格中插入Html

public void insertHtmlToTableCell() {
        //  构建一个html内容
        String content = "<p style=\"color:red\">一段HTML</p>";

        WordprocessingMLPackage aPackage;
        try {
            //  创建一个临时文件
            File tempFile = File.createTempFile("test", ".docx");
            aPackage = WordprocessingMLPackage.createPackage();
            MainDocumentPart mainDocumentPart = aPackage.getMainDocumentPart();
            mainDocumentPart.addStyledParagraphOfText("Title", "将HTML插入表格中");

            int rowsNum = 2;    //  生成表格的行数
            int columnNumber = 2;   //  生成表格的列数
            int writableWidthTwips = aPackage.getDocumentModel().getSections().get(0).getPageDimensions().getWritableWidthTwips();  //  文档的可写宽度

            //  创建表格对象
            Tbl tbl = TblFactory.createTable(rowsNum, columnNumber, writableWidthTwips / columnNumber);
            //  获取所有行对象
            List<Object> rows = tbl.getContent();
            setRowData(mainDocumentPart, rows, 0, "第一行", content);
            setRowData(mainDocumentPart, rows, 1, "第二行", content);
            //  将生成的表格插入到文档中
            mainDocumentPart.addObject(tbl);
            //  将构建的word内容保存到临时文件
            aPackage.save(tempFile);
        } catch (IOException | Docx4JException e) {
            e.printStackTrace();
        }
    }

    /**
     * 设置生成的教案word的行数据
     * @param mainDoc   MainDocumentPart对象
     * @param rows  创建的Tbl对象的所有行对象
     * @param rowIndex  操作的行的索引
     * @param label     第一列插入的内容
     * @param htmlContent   第二列插入的html内容(只需要核心html段就可以了)
     * @throws InvalidFormatException
     */
    private void setRowData(MainDocumentPart mainDoc, List<Object> rows, int rowIndex, String label, String htmlContent) throws InvalidFormatException {
        //  获取当前行
        Tr tr = (Tr) rows.get(rowIndex);
        //  获取所有列对象
        List<Object> cells = tr.getContent();
        Tc labelTc = (Tc) cells.get(0); //  label列
        Tc valueTc = (Tc) cells.get(1); //  content列

        //  设置label
        labelTc.getContent().add(createLabelP(label));
        //  设置content
        if (htmlContent != null) {
            /*
              这里需要格外注意:
              1. 必须额外加上<p><br/></p>,其中<br/>可为其它标签或非空内容,否则会导致生成的word有错误,无法打开
              2. 需要设置html的字符集,否则html内容在部分word版本或跨平台word中会出现中文乱码的情况
             */
            String contentStr = "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html\"; charset=\"utf-8\"></head><body>" + htmlContent + "<p><br/></p></body></html>";
            //  创建并设置AlternativeFormatInputPart
            AlternativeFormatInputPart afiPart = new AlternativeFormatInputPart(new PartName("/hw" + rowIndex + ".html")); //CAUTION: each html part needs a new name!!
            afiPart.setBinaryData(contentStr.getBytes(Charsets.UTF_8));
            afiPart.setContentType(new ContentType("text/html"));
            //  创建CTAltChunk
            Relationship altChunkRel = mainDoc.addTargetPart(afiPart);
            CTAltChunk ac = Context.getWmlObjectFactory().createCTAltChunk();
            ac.setId(altChunkRel.getId());
            //  将ac写入第二列(前面的索引好像是指在哪个位置插入,具体自己查查吧~~~)
            valueTc.getContent().set(0, ac);
        }
    }

    /**
     * 创建普通的Label的样式配置
     * @param text  内容
     * @return  一个P节点
     */
    private P createLabelP(String text) {
        ObjectFactory factory = Context.getWmlObjectFactory();
        P p = factory.createP();
        R r = factory.createR();
        Text t = factory.createText();
        t.setValue(text);
        r.getContent().add(t);
        p.getContent().add(r);
        RPr rpr = factory.createRPr();
        BooleanDefaultTrue b = new BooleanDefaultTrue();
        rpr.setB(b);
        BooleanDefaultTrue caps = new BooleanDefaultTrue();
        rpr.setCaps(caps);
        Color green = factory.createColor();
        green.setVal("black");
        rpr.setColor(green);

        // 设置字体大小
        HpsMeasure size = new HpsMeasure();
        size.setVal(new BigInteger("18"));
        rpr.setSz(size);
        rpr.setSzCs(size);
        // 设置字体
        RFonts rFonts = rpr.getRFonts();
        if (rFonts==null) {
            rFonts = new RFonts();
            rpr.setRFonts(rFonts);
        }
        rFonts.setEastAsia("微软雅黑");

        r.setRPr(rpr);
        return p;
    }

结果:


image

一些坑

  1. 在插入HTML的时候,一定要是完整的html内容(以<html>节点开口)
  2. 需要设置html的字符集,否则html内容在部分word版本或跨平台word中会出现中文乱码的情况
  3. 当在表格中插入HTML内容时,最后在</body>节点之前再添加个节点,如:<p><br/></p>,不然可能会遇到生成的word错误,无法打开的情况(我就遇到过:当<body>节点中的内容仅为一个<table>节点时)
上一篇下一篇

猜你喜欢

热点阅读