要处理的目标文档中包含大量表格及各级标题,在解析表格内容前要求先将文档结构提取出来,也就是要将各级标题及标题编号读出来
找到了以下三种方法。
一.逐段扫描判断
1 /** 2 * 预处理Word文档 3 * @param 存储标题的容器 4 * @return 5 */ 6 public ArrayList<Heading> pretreatWord(ArrayList<Heading>headings){ 7 word=new ActiveXComponent("Word.Application"); 8 word.setProperty("Visible", new Variant(false)); 9 documents=word.getProperty("Documents").toDispatch(); 10 wordFile=Dispatch.invoke(documents, "Open", Dispatch.Method, new Object[]{filePath,new Variant(true),new Variant(true)}, new int[1]).toDispatch(); 11 paragraphs=Dispatch.get(wordFile, "Paragraphs").toDispatch(); 12 //段落总数 13 int paraCount=Dispatch.get(paragraphs, "Count").getInt(); 14 //表格总数 15 int tableCount=Dispatch.get(tables, "Count").getInt(); 16 int tableNum=1; 17 //是否能进行跳过表格操作 18 boolean canSkip=false; 19 int flag=0; 20 try{ 21 for(int i=0;i<paraCount;++i){ 22 Dispatch paragraph=Dispatch.call(paragraphs, "Item",new Variant(i+1)).toDispatch(); 23 int outline=Dispatch.get(paragraph, "OutlineLevel").getInt(); 24 //如果大纲等级为正文 25 // System.out.println("第"+(i+1)+"段"); 26 //该文档中标题最大到4级,大于4级为正文部分 27 //当遇到正文部分,判断是否可进行跳跃 28 if(outline>4){ 29 if(canSkip){ 30 i=skipTable(tableNum,i); 31 canSkip=false; 32 tableNum++; 33 continue; 34 } 35 else{continue;} 36 } 37 System.out.println("******************"); 38 //如果大纲等级为标题 39 Dispatch paraRange=Dispatch.get(paragraph, "Range").toDispatch(); 40 //存入不同的集合 41 switch(outline){ 42 case 1: headings.add(new Heading(1,Dispatch.get(paraRange, "Text").toString()));break; 43 case 2: headings.add(new Heading(2,Dispatch.get(paraRange, "Text").toString()));flag++;break; 44 case 4: headings.add(new Heading(4,Dispatch.get(paraRange, "Text").toString()));break; 45 case 5: headings.add(new Heading(5,Dispatch.get(paraRange, "Text").toString()));break; 46 case 6: headings.add(new Heading(6,Dispatch.get(paraRange, "Text").toString()));break; 47 default: break; 48 } 49 if(flag!=1){ 50 canSkip=true;} 51 } 52 }catch(Exception e){ 53 e.printStackTrace(); 54 }finally{ 55 Dispatch.call(wordFile, "Close",saveOnExit); 56 //关闭word程序 57 word.invoke("Quit",new Variant[]{}); 58 System.out.println("--end--"); 59 } 60 return headings; 61 }
由于word中每个表格的单元格都占用一个段落,因此如果真的逐段扫描速度会很慢(我操作的文档算上表格4000多段...)。因此当扫描到表格部分时可进行跳跃。
程序开始可获得所有表格的集合tables,当遇到大纲等级>4时,可取出一个表格,得到它占用的总段落数,进行跳跃。
二.切换大纲等级
1 Dispatch aw=Dispatch.get(wordFile, "ActiveWindow").toDispatch(); 2 Dispatch view=Dispatch.get(aw, "View").toDispatch(); 3 view.put(view, "Type", 2); 4 //由于一级标题可能被分为2行显示,因此需判断 5 //变量extra作为偏移量。若一级标题分为两行,则偏移量为2(含"目录"项的一行); 6 //若一级标题为一行,则偏移量为1(表示"目录"项的一行) 7 Dispatch.call(view, "ShowHeading",1); 8 paragraphs=Dispatch.get(wordFile, "Paragraphs").toDispatch(); 9 int extra=Dispatch.get(paragraphs, "Count").getInt(); 10 view.put(view, "Type", 3); 11 view.put(view, "Type", 2); 12 //显示4级及以上的标题 13 Dispatch.call(view, "ShowHeading",4); 14 paragraphs=Dispatch.get(wordFile, "Paragraphs").toDispatch();
1 wdMasterView 5 主控视图。 2 wdNormalView 1 普通视图。 3 wdOutlineView 2 大纲视图。 4 wdPrintPreview 4 打印预览视图。 5 wdPrintView 3 页面视图。 6 wdReadingView 7 阅读视图。 7 wdWebView 6 Web 视图。
这种方法能获得标题的文字内容,但标题编号无法获得。
三.读取套用编号格式的段落
1 Dispatch listParagraphs=Dispatch.get(wordFile, "ListParagraphs").toDispatch(); 2 int lpCount=Dispatch.get(listParagraphs, "Count").getInt(); 3 for(int i=1;i<=lpCount;++i){ 4 Dispatch listParagraph=Dispatch.call(listParagraphs, "Item",i).toDispatch(); 5 Dispatch listRange=Dispatch.get(listParagraph, "Range").toDispatch(); 6 Dispatch listFormat=Dispatch.get(listRange, "ListFormat").toDispatch(); 7 //标题编号 8 String listString=Dispatch.get(listFormat, "ListString").toString(); 9 //标题文字 10 String text=Dispatch.get(listRange, "Text").toString(); 11 text=text.replaceAll("\r", ""); 12 //大纲等级 13 int level=Dispatch.get(listParagraph, "OutlineLevel").getInt(); 14 }
这种方法能将标题内容全部取出,速度最快。缺点是如果标题编号没有套用编号格式自动生成,而是手动添加的,这样的标题段会被漏掉。