Docx4j简单学习

前言: 此文档简单记述在使用docx4j进行编程式生成文档元素的个人心得,故存在理解有误之处,还请指正!

  • 该项目是基于docx文档的xml结构,进行标签对象的赋值与取值,因此,当生成部分不常见元素时(比如无序项目编码时),可以参考xml文件中的属性,进行编码实现。
    1. 比如文档中插入小标题,即文本添加导航功能:
      文档内容如下:
      Docx4j简单学习_第1张图片

    2. 对应解压文件
      Docx4j简单学习_第2张图片
      document.xml 即文档xml结构内容,styles.xml即为样式文件

    3. document.xml内容
      Docx4j简单学习_第3张图片
      val是style中的样式id,那么对用的style.xml文件内容如下:
      Docx4j简单学习_第4张图片
      标签将样式与导航窗格绑定,它指定了样式的大纲视图层级,val属性的值代表的是层级。
      那如何实现为文本增加标题导航?
      首先,我们需要定义一个样式:

          WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
      //创建docx4j工厂
      ObjectFactory factory = Context.getWmlObjectFactory();
      //获得word包中document.xml文件内容
      MainDocumentPart main = wordMLPackage.getMainDocumentPart();
      //获得styles.xml文件内容
      StyleDefinitionsPart sdp = main.getStyleDefinitionsPart();
      //创建一个样式标签
      Style style = factory.createStyle();
      //设置样式标签的type属性
      style.setType("paragraph");
      //新建name标签
      Name name = new Name();
      //设置name标签的val属性
      name.setVal("test");
      //将设置好的name标签设置到样式标签中
      style.setName(name);
      //设置样式标签的id属性
      style.setStyleId("test");
      //创建段落格式标签
      PPr ppr = factory.createPPr();
      //创建大纲级别标签
      OutlineLvl lvl = new OutlineLvl();
      //设置大纲级别标签的val属性为0
      lvl.setVal(BigInteger.valueOf(0));
      //将设置好的大纲级别标签设置到段落格式标签中
      ppr.setOutlineLvl(lvl);
      //将设置好的段落格式标签设置到样式标签中
      style.setPPr(ppr);
      //将设置好的段落标签加入到styles.xml文件中
      sdp.getContents().getStyle().add(style);
      //将创建的样式,添加到段落中
      //获得document.xml文件下body标签内容
      Body body = main.getContents().getBody();
      //创建段落标签
      P p = factory.createP();
      //创建段落格式标签
      PPr pPr = factory.createPPr();
      //创建段落样式标签
      PStyle ps = new PStyle();
      //设置段落样式标签的val属性值为前面创建的样式id
      ps.setVal("Heading1");
      //将设置好的段落样式标签设置到段落格式标签中
      pPr.setPStyle(ps);
      //将设置好的段落格式标签设置到段落标签中
      p.setPPr(pPr);
      //创建r标签
      R run = factory.createR();
      //创建t标签
      Text t = factory.createText();
      //设置t标签内的内容
      t.setValue("测试内容");
      //将设置好的t标签设置到r标签中
      run.getContent().add(t);
      //将设置好的r标签设置到段落标签中
      p.getContent().add(run);
      //将设置好的段落标签加入body标签中
      body.getContent().add(p);
      //设置word文档要存放的文件
      File file = new File("保存路径");
      //将设置好的word包保存到指定文件中
      wordMLPackage.save(file);
      
    4. 测试结果
      Docx4j简单学习_第5张图片

  • 如何理解项目中P与R
    P是文本顶级标签,在xml中与文本有关结构(比如,项目符号)都需要该标签,因此可以嵌到其他标签中去,但是其它标签很难相互嵌套。它有两个重要的子标签,rPr设置文本属性,比如字体、颜色、下划线等,pPr设置P的样式,比如缩进等。它们的关系可以总结为:
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GFOZcpLS-1631796377060)(vx_images/4915000242393.png)]
    R是理解为混合数据类型,这里可以作为一段文本对象,接受text和rPR等关于文本一切的属性设置,这样可以在段落中,设置不同样式的文本,最后都装载到P中。
  • 如何实现一般的项目符号,这里只举例数字编号和原点符号,其它特殊符号实现尚不得知。
  private static void createBulletedItem(MainDocumentPart wordMLPackage,
                                           String info) throws InvalidFormatException, JAXBException {
        NumberingDefinitionsPart ndp = new NumberingDefinitionsPart();
        wordMLPackage.addTargetPart(ndp);
        ndp.unmarshalDefaultNumbering();
        //必须加载上述信息

        ObjectFactory factory = new org.docx4j.wml.ObjectFactory();
        P p = factory.createP();
        org.docx4j.wml.Text t1 = factory.createText();
        t1.setValue(info);
        org.docx4j.wml.R run = factory.createR();
        run.getContent().add(t1);

        org.docx4j.wml.PPr ppr = factory.createPPr();
        p.setPPr(ppr);

        // Create and add 
        PPrBase.NumPr numPr = factory.createPPrBaseNumPr();
        ppr.setNumPr(numPr);

        // The  element
        PPrBase.NumPr.Ilvl ilvlElement = factory.createPPrBaseNumPrIlvl();
        numPr.setIlvl(ilvlElement);
        ilvlElement.setVal(BigInteger.valueOf(0));

        // 查阅了相关英文文档,初步认定:0是删除项目编号,1是(数字编号)有序列表,2是无序列表
        PPrBase.NumPr.NumId numIdElement = factory.createPPrBaseNumPrNumId();
        numPr.setNumId(numIdElement);
        numIdElement.setVal(BigInteger.valueOf(2));

        p.getContent().add(run);
        wordMLPackage.addObject(p);
    }

我们之前说过,项目符号也是本文的一种,只是样式改变了,即每一个item即为一个P。

  • 因为xml结构获取对象比较繁琐,所以在使用外用轮子需注意,倾向于以下这种,在获得对象之间,先做判断,如果直接生成新的对象,会出现对象相互覆盖的问题。
    public static TrPr getTrPr(Tr tr) {
        TrPr trPr = tr.getTrPr();
        if (trPr == null) {
            trPr = new TrPr();
            tr.setTrPr(trPr);
        }
        return trPr;
    }
  • 实现Tab或者代替文本空格
R.Tab rtab = factory.createRTab();
JAXBElement rtabWrapped = factory.createRTab(rtab);
r.getContent().add(rtabWrapped);
  • 文档生成大部分元素都可以通过网上查询与项目一的方法解决,这里提供一些参考资料,方便查阅
  1. 表格与文本工具类
  2. 方法功能查询,需科学上网

你可能感兴趣的:(文档生成,java,xml,经验分享)