天天看点

JACOB 完整读取文档大纲(目录)(各级标题项内容)并跳过表格 提高效率

为了精准的获取目录的页码、内容、以及前置标题列,我才去的是逐段读取的方式,但由于word中每个表格的单元格都占用一个段落,因此如果真的逐段扫描速度会很慢。因此可以在读取之前把表格给干掉。

  • 获取所有表格
//所有表格
Dispatch tables = Dispatch.get(doc, "Tables").toDispatch(); 
//获取表格总数
int tableCount = Dispatch.get(tables, "Count").getInt();
           
  • 删除所有表格

    在这里我做的是打开文档和读取大纲操作,不会对其进行保存·操作,所以结束后对文档内容本身是不会有影响。

for (int i =  ; i < tableCount ; i++) {
    table = Dispatch.call(tables, "Item", new Variant()).toDispatch();
    Dispatch.call(table, "Delete");
}
           
完整代码如下
  • 在这里要解释一下为什么要从后往前读。
  • 因为我这里需求是需要读取文档目录并有相应的目录结构(层次关系,比如说1 下面有1.1 和1.2 ,1.1下面有1.1.1),并转换成json字符串发送到移动端,移动端通过json字符串展示目录,并能通过页码索引到对应的位置。
  • 所以这里我就没改动读取方向了,有问题可以多多交流,JACOB坑太多了,可以多交流交流。
public class ReadWordOrWPSBookMarks {
    /**
     * 读取word/wps文档的大纲
     * @param filename  要打开的文档的目录(带文件名)
     * @param strChoose 打开方式  Microsoft Word: 2   WPS: 3
     */
    public static void readBookMarksByWordOrWps(String filename, String strChoose) {
        ActiveXComponent app = null;
        Dispatch doc = null;
        try {
            //microsoft Office 方式
            if ( "2".equals(strChoose) ) {
                app = new ActiveXComponent("Word.Application");
            }
            //WPS 方式
            if ( "3".equals(strChoose) ) {
                app = new ActiveXComponent("KWPS.Application");
            }
            app.setProperty("Visible", new Variant(false));
            Dispatch docs = app.getProperty("Documents").toDispatch();
            doc = Dispatch.call(docs, "Open", filename).toDispatch();

            //所有表格
            Dispatch tables = Dispatch.get(doc, "Tables").toDispatch(); 
            //获取表格总数
            int tableCount = Dispatch.get(tables, "Count").getInt();
            System.out.println("表格数" + tableCount);
            Dispatch table = null;
            //删除所有表格(删除第一个表格后,第二个表格会变成第一表格)
            for (int i =  ; i < tableCount ; i++) {
                table = Dispatch.call(tables, "Item", new Variant()).toDispatch();
                Dispatch.call(table, "Delete");
            }

            // 获取大纲列表
            Dispatch paragraphs = Dispatch.get(doc, "Paragraphs").toDispatch();
            int count = Dispatch.get(paragraphs, "Count").getInt();//大纲数量
            //当前大纲等级层次
            int tempLevel = ;
            //从后往前获取大纲
            for (int i = count -  ; i >= ; i--) {
                //当前大纲项
                Dispatch paragraph = Dispatch.call(paragraphs, "Item", new Variant(i+)).toDispatch();
                //大纲等级
                int level = Dispatch.get(paragraph, "OutlineLevel").getInt();
                Dispatch paragraphRange  = Dispatch.get(paragraph, "Range").toDispatch();
                //一般目录不会超过4级,4级往后是内容,可以跳过
                if ( level <=  ) {
                    if ( tempLevel ==  ) {
                        tempLevel = level ;
                    }
                    //标题编号
                    Dispatch listFormat = Dispatch.get(paragraphRange, "ListFormat").toDispatch();
                    String listString = "";
                    try {
                        listString = Dispatch.get(listFormat, "ListString").toString();
                    } catch (Exception e) {
                        System.out.println("没有ListForat属性的标题:" + Dispatch.get(paragraphRange, "Text").toString().replaceAll("\\\r|\\\f", ""));
                    }
                    //标题
                    String text = Dispatch.get(paragraphRange, "Text").toString().replaceAll("\\\r|\\\f", "") ;
                    //可能会存在一些为空的隐藏的大纲,text是为空的
                    if (text == null || ("").equals(text)) {
                        continue;
                    }
                    text = listString + text;
                    //索引的页码
                    int page = Dispatch.call(paragraphRange, "information", ).getInt() ;

                    System.out.println("text:"+text + "   page:"+page + "   level:"+level);
                }
            }
        } catch (Exception e) {
            System.out.println(" 大纲获取失败" , e);
        } finally {
            try {
                Dispatch.call(doc, "Close", false);
                if (app != null){
                    app.invoke("Quit", new Variant[] {});
                    app = null;
                }   
            } catch (Exception e2) {
                System.out.println("关闭ActiveXComponent异常");
            }
        }
    }
           

继续阅读