要處理的目標文檔中包含大量表格及各級標題,在解析表格內容前要求先將文檔結構提取出來,也就是要將各級標題及標題編號讀出來
找到了以下三種方法。
一.逐段掃描判斷
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 }
這種方法能將標題內容全部取出,速度最快。缺點是如果標題編號沒有套用編號格式自動生成,而是手動添加的,這樣的標題段會被漏掉。