java poi 读取.doc审阅 修订 最终状态 问题

一、前景


    在使用java poi读取.doc文件,遇到审阅 修订 功能时,poi 不能读取修定状态为“最终状态”的数据,而是读取了所有修定内容,如下图所示:

  1. 文本读取内容:
    image
  2. 正确内容:
    image

二、POI 类结构分析


  1. 根据 官网API 我们知道 poi 读取.doc 有三个主要的类:
  • HWPFDocument:这个类包含了所有.doc文件的结构支持。
  • HWPFDocumentCore:这个类包含了 Word 文档的大部分核心基本功能,但是没有一些表结构信息
  • HWPFOldDocument:为旧文件(Word 6/Word 95)提供非常简单的支持。
  1. 类结构 关键点思维导图分析
    image

三、代码解决


1、maven 依赖

      <dependency>
          <groupId>org.apache.poi</groupId>
          <artifactId>poi</artifactId>
          <version>4.1.2</version>
      </dependency>
      <dependency>
          <groupId>org.apache.poi</groupId>
          <artifactId>poi-scratchpad</artifactId>
          <version>4.1.2</version>
      </dependency>
      <dependency>
          <groupId>org.apache.poi</groupId>
          <artifactId>poi-ooxml</artifactId>
          <version>4.1.2</version>
      </dependency>

2、关键代码

import com.ygsoft.rpa.scene.word.WordConst;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.usermodel.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * .doc类的文档读取(文本与表格数据)
 * jalan.wang
 * http://www.jalan.wang
 */
public class WordDoc {
    private final Range range;
    private final List<Table> allTables = new ArrayList<>();

    public WordDoc(File file) throws IOException {
        // 处理doc格式 即office2003版本
        POIFSFileSystem pfs = new POIFSFileSystem(file, true);
        HWPFDocument hwpf = new HWPFDocument(pfs);
        range = hwpf.getRange();//得到文档的读取范围
        TableIterator tables = new TableIterator(range);
        while (tables.hasNext()) {
            Table table = tables.next();
            allTables.add(table);
        }
    }

    public String readParagraphContent() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < range.numParagraphs(); i++) {
            Paragraph paragraph = range.getParagraph(i);
            //如果段落 是在 table中 就跳过,此处只处理普通文本内容
            if (paragraph.isInTable())
                continue;
            String value = getFinishValue(paragraph);
            if (StringUtils.isBlank(value))
                continue;
            sb.append(value).append("\r\n");
        }
        System.out.println(sb);
        return sb.toString();
    }

    public void readTable() {
        List<String> rows = new ArrayList<>();
        for (Table table : allTables) {
            //迭代行,默认从0开始,可以依据需要设置i的值,改变起始行数,也可设置读取到那行,只需修改循环的判断条件即可
            for (int rowIndex = 0; rowIndex < table.numRows(); rowIndex++) {
                TableRow tr = table.getRow(rowIndex);
                String rowValue = getRowValue(tr, rowIndex);
                rows.add(rowValue);
            }
        }
        System.out.println(String.join("\r\n", rows));
    }

    private String getRowValue(TableRow tr, int rowIndex) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < tr.numCells(); i++) {
            TableCell td = tr.getCell(i);//取得单元格
            for (int j = 0; j < td.numParagraphs(); j++) {
                Paragraph paragraph = td.getParagraph(j);
                String value = getFinishValue(paragraph);
                //去除后面的特殊符号
                if (StringUtils.isNotBlank(value)) {
                    value = value.substring(0, value.length() - 1);
                }
                sb.append(value);
            }
            sb.append("[").append(rowIndex).append(",").append(i).append("]").append(" ");
        }
        return sb.toString();
    }

    /**
     * 获取Doc 审阅模式下,修订:最终状态 数据
     *
     * @param paragraph 文本段落
     * @return 返回 修订:最终状态 数据
     */
    @NotNull
    private String getFinishValue(Paragraph paragraph) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < paragraph.numCharacterRuns(); i++) {
            CharacterRun run = paragraph.getCharacterRun(i);
            //如果当前字符块 是一个删除标记,就跳过,只取最终修订版内容
            if (run.isMarkedDeleted())
                continue;
            String value = run.text();
            value = value.replace(WordConst.BLANK_CN, WordConst.BLANK).replace(WordConst.BLANK_EN, WordConst.BLANK);
            if (StringUtils.isBlank(value)) continue;
            sb.append(value);
        }
        return sb.toString();
    }

    public static void main(String[] args) throws Exception {
        File file = new File("E:\\Users\\desktop\\测试带修订内容的文档.doc");
        WordDoc wordDoc = new WordDoc(file);
        wordDoc.readParagraphContent();
        wordDoc.readTable();
    }
}

posted on 2022-11-19 20:22  Jalan·Wang  阅读(1061)  评论(0编辑  收藏  举报

导航