Apache POI Word - 段落

Last Modified: 2023/11/05

概述

上一篇中我们讲述了如何创建和保存文档,本篇接着上一篇,讲述如何往文档中添加段落和文字以及如何改变文字的样式。

文档的组成部分

一个文档通常包含一个标题,若干个二级、三级(四级五级。。。如果你愿意的话)标题,每个标题下面通常包含一个或者多个段落,每个段落里面又包含多个文字。

当然文档中还可以包含表格、图片和视频等,这不是本文的内容,这些内容在后续文章中会有说明。

给文档添加段落和文字

创建段落并添加文字:

XWPFParagraph p = doc.createParagraph();
XWPFRun run = p.createRun();
run.setText("this this the text in paragraph");

是不是很简单?但是我觉得还不够简洁,如果 XWPFParagraph 直接有个 addText(String text) 方法是不是更简单?为什么 POI 的 api 要设计一个 Run 对象来承载文字?什么是 Run 呢?

在回答这个问题之前,让我们先创建一个 run.docx 文档,然后在文档中放入如下文字。

然后将文档重命名为 run.zip,解压然后看看 document.xml 文件的内容

从这个 xml 结构是不是看出点什么门道了?POI 的 api 正是和这个 xml 结构保持一致的。<w:p><w:paragraph> 的缩写,同理 <w:r> 其实应该是 <w:run> 的缩写。<w:rPr> 则是 <w:runProperites> 的缩写。

Run 用来承载具有相同样式的一段文字。由于”This is red text,but this is becomes green.“ 这句话包含了两种样式,因此有两个 Run 对象。

有了上面的铺垫,再看看通过 POI api 来生成这段文字的代码是不是很容易理解?

package net.verytools.tutorial;

import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;

import java.io.FileOutputStream;
import java.io.IOException;

public class CreateDoc {

  public static void main(String[] args) throws IOException {
    XWPFDocument doc = new XWPFDocument();
    XWPFParagraph p = doc.createParagraph();
    
    XWPFRun run1 = p.createRun();
    run1.setColor("FF0000");
    run1.setText("This is red text,");
    
    XWPFRun run2 = p.createRun();
    run2.setColor("00FF00");
    run2.setText("but this is becomes green.");
    // ...
  }
}

Run 对象除了可以设置颜色之外,还可以设置字体、字体大小、字体是否加粗等。

// 设置字体大小
run1.setFontSize(16);
// 设置字体
run1.setFontFamily("Arial Black");
// 字体加粗
run1.setBold(true);

段落中换行也是通过 Run 对象实现的

XWPFParagraph p = doc.createParagraph();
XWPFRun run = p.createRun();
run.addBreak(BreakType.TEXT_WRAPPING);

给文档一个标题

标题应该用什么 api 来生成呢? 前面我们提到 docx 文档的本质是一个包含多个 xml 和媒体文件的 zip 文件,那么我们在 docx 文档中插入一个一级标题,然后将 docx 后缀 改成 .zip,解压看看 xml 是不是有所启发呢?

<w:body>
  <w:p>
    <w:pPr>
      <w:pStyle w:val="2"/>
      <w:bidi w:val="0"/>
      <w:rPr>
        <w:rFonts w:hint="default"/>
        <w:lang w:val="en-US" w:eastAsia="zh-CN"/>
      </w:rPr>
    </w:pPr>
    <w:r>
      <w:rPr>
        <w:rFonts w:hint="eastAsia"/>
        <w:lang w:val="en-US" w:eastAsia="zh-CN"/>
      </w:rPr>
      <w:t>This is the title</w:t>
    </w:r>
  </w:p>
</w:body>

<w:p>可以看出标题也是一个段落。从 <w:pStyle w:val="2"/> 可以看出标题应用了一个 id 为 ”2“ 的样式,从 styles.xml 中可以找到 id 为 ”2“ 的样式。

从图中可以看出该样式指定了字体大小为 44、字体加粗且样式的名称为 “heading 1”。<w:basedOn w:val="1"/>表明该样式基于 id 为 1 的样式。id 为 1 的样式这里就不放图了,该样式中指定了对齐方式为居中对齐。

注意:xml 中的 <w:sz w:val="44"/> 的单位是 half-point(半点),因此字体大小实际为 22pt。

样式的好处是复用,我们可以在文档的多个部分应用同一个样式。如何使用 POI 生成样式呢?这个问题将在后续的文章中说明。暂时我们不使用样式,通过设置合适的字体大小并加粗字体来模拟标题。

try (XWPFDocument doc = new XWPFDocument()) {
  try (FileOutputStream out = new FileOutputStream("D:\\tmp\\simpledoc.docx")) {
    XWPFParagraph p = doc.createParagraph();
    // 居中对齐
    p.setAlignment(ParagraphAlignment.CENTER);
    XWPFRun run = p.createRun();
    // 加粗
    run.setBold(true);
    // 字体大小为 44 half-point
    run.setFontSize(22);
    run.setFontFamily("Calibri");
    run.setText("This is title");
    doc.write(out);
  }
}

虽然我们没有使用样式,但是我们生成的标题和使用 Office 软件制作的一级标题的样式看上去基本相同,不过需要说明的这个只是显示效果近似而已,标题还有一个重要的特性便是大纲级别。这一点我们会在后续讲到样式的时候另行说明。

>> 返回目录

有问题吗?点此反馈!

温馨提示:反馈需要登录