国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

java Apache poi 對word doc文件進行讀寫操作

2019-11-26 13:20:06
字體:
供稿:網(wǎng)友

使用POI讀寫Word doc文件

       Apache poi的hwpf模塊是專門用來對word doc文件進行讀寫操作的。在hwpf里面我們使用HWPFDocument來表示一個word doc文檔。在HWPFDocument里面有這么幾個概念:

  Range:它表示一個范圍,這個范圍可以是整個文檔,也可以是里面的某一小節(jié)(Section),也可以是某一個段落(Paragraph),還可以是擁有共同屬性的一段文本(CharacterRun)。

  Section:word文檔的一個小節(jié),一個word文檔可以由多個小節(jié)構(gòu)成。

  Paragraph:word文檔的一個段落,一個小節(jié)可以由多個段落構(gòu)成。

  CharacterRun:具有相同屬性的一段文本,一個段落可以由多個CharacterRun組成。

  Table:一個表格。

  TableRow:表格對應的行。

  TableCell:表格對應的單元格。

       Section、Paragraph、CharacterRun和Table都繼承自Range。

1       讀word doc文件

       在日常應用中,我們從word文件里面讀取信息的情況非常少見,更多的還是把內(nèi)容寫入到word文件中。使用POI從word doc文件讀取數(shù)據(jù)時主要有兩種方式:通過WordExtractor讀和通過HWPFDocument讀。在WordExtractor內(nèi)部進行信息讀取時還是通過HWPFDocument來獲取的。

1.1     通過WordExtractor讀文件

       在使用WordExtractor讀文件時我們只能讀到文件的文本內(nèi)容和基于文檔的一些屬性,至于文檔內(nèi)容的屬性等是無法讀到的。如果要讀到文檔內(nèi)容的屬性則需要使用HWPFDocument來讀取了。下面是使用WordExtractor讀取文件的一個示例:

public class HwpfTest {   @SuppressWarnings("deprecation")  @Test  public void testReadByExtractor() throws Exception {   InputStream is = new FileInputStream("D://test.doc");   WordExtractor extractor = new WordExtractor(is);   //輸出word文檔所有的文本   System.out.println(extractor.getText());   System.out.println(extractor.getTextFromPieces());   //輸出頁眉的內(nèi)容   System.out.println("頁眉:" + extractor.getHeaderText());   //輸出頁腳的內(nèi)容   System.out.println("頁腳:" + extractor.getFooterText());   //輸出當前word文檔的元數(shù)據(jù)信息,包括作者、文檔的修改時間等。   System.out.println(extractor.getMetadataTextExtractor().getText());   //獲取各個段落的文本   String paraTexts[] = extractor.getParagraphText();   for (int i=0; i<paraTexts.length; i++) {     System.out.println("Paragraph " + (i+1) + " : " + paraTexts[i]);   }   //輸出當前word的一些信息   printInfo(extractor.getSummaryInformation());   //輸出當前word的一些信息   this.printInfo(extractor.getDocSummaryInformation());   this.closeStream(is);  }   /**  * 輸出SummaryInfomation  * @param info  */  private void printInfo(SummaryInformation info) {   //作者   System.out.println(info.getAuthor());   //字符統(tǒng)計   System.out.println(info.getCharCount());   //頁數(shù)   System.out.println(info.getPageCount());   //標題   System.out.println(info.getTitle());   //主題   System.out.println(info.getSubject());  }   /**  * 輸出DocumentSummaryInfomation  * @param info  */  private void printInfo(DocumentSummaryInformation info) {   //分類   System.out.println(info.getCategory());   //公司   System.out.println(info.getCompany());  }   /**  * 關閉輸入流  * @param is  */  private void closeStream(InputStream is) {   if (is != null) {     try {      is.close();     } catch (IOException e) {      e.printStackTrace();     }   }  } }  

1.2     通過HWPFDocument讀文件

       HWPFDocument是當前Word文檔的代表,它的功能比WordExtractor要強。通過它我們可以讀取文檔中的表格、列表等,還可以對文檔的內(nèi)容進行新增、修改和刪除操作。只是在進行完這些新增、修改和刪除后相關信息是保存在HWPFDocument中的,也就是說我們改變的是HWPFDocument,而不是磁盤上的文件。如果要使這些修改生效的話,我們可以調(diào)用HWPFDocument的write方法把修改后的HWPFDocument輸出到指定的輸出流中。這可以是原文件的輸出流,也可以是新文件的輸出流(相當于另存為)或其它輸出流。下面是一個通過HWPFDocument讀文件的示例:

public class HwpfTest {   @Test  public void testReadByDoc() throws Exception {   InputStream is = new FileInputStream("D://test.doc");   HWPFDocument doc = new HWPFDocument(is);   //輸出書簽信息   this.printInfo(doc.getBookmarks());   //輸出文本   System.out.println(doc.getDocumentText());   Range range = doc.getRange();//  this.insertInfo(range);   this.printInfo(range);   //讀表格   this.readTable(range);   //讀列表   this.readList(range);   //刪除range   Range r = new Range(2, 5, doc);   r.delete();//在內(nèi)存中進行刪除,如果需要保存到文件中需要再把它寫回文件   //把當前HWPFDocument寫到輸出流中   doc.write(new FileOutputStream("D://test.doc"));   this.closeStream(is);  }   /**  * 關閉輸入流  * @param is  */  private void closeStream(InputStream is) {   if (is != null) {     try {      is.close();     } catch (IOException e) {      e.printStackTrace();     }   }  }   /**  * 輸出書簽信息  * @param bookmarks  */  private void printInfo(Bookmarks bookmarks) {   int count = bookmarks.getBookmarksCount();   System.out.println("書簽數(shù)量:" + count);   Bookmark bookmark;   for (int i=0; i<count; i++) {     bookmark = bookmarks.getBookmark(i);     System.out.println("書簽" + (i+1) + "的名稱是:" + bookmark.getName());     System.out.println("開始位置:" + bookmark.getStart());     System.out.println("結(jié)束位置:" + bookmark.getEnd());   }  }   /**  * 讀表格  * 每一個回車符代表一個段落,所以對于表格而言,每一個單元格至少包含一個段落,每行結(jié)束都是一個段落。  * @param range  */  private void readTable(Range range) {   //遍歷range范圍內(nèi)的table。   TableIterator tableIter = new TableIterator(range);   Table table;   TableRow row;   TableCell cell;   while (tableIter.hasNext()) {     table = tableIter.next();     int rowNum = table.numRows();     for (int j=0; j<rowNum; j++) {      row = table.getRow(j);      int cellNum = row.numCells();      for (int k=0; k<cellNum; k++) {        cell = row.getCell(k);        //輸出單元格的文本        System.out.println(cell.text().trim());      }     }   }  }   /**  * 讀列表  * @param range  */  private void readList(Range range) {   int num = range.numParagraphs();   Paragraph para;   for (int i=0; i<num; i++) {     para = range.getParagraph(i);     if (para.isInList()) {      System.out.println("list: " + para.text());     }   }  }   /**  * 輸出Range  * @param range  */  private void printInfo(Range range) {   //獲取段落數(shù)   int paraNum = range.numParagraphs();   System.out.println(paraNum);   for (int i=0; i<paraNum; i++) {//    this.insertInfo(range.getParagraph(i));     System.out.println("段落" + (i+1) + ":" + range.getParagraph(i).text());     if (i == (paraNum-1)) {      this.insertInfo(range.getParagraph(i));     }   }   int secNum = range.numSections();   System.out.println(secNum);   Section section;   for (int i=0; i<secNum; i++) {     section = range.getSection(i);     System.out.println(section.getMarginLeft());     System.out.println(section.getMarginRight());     System.out.println(section.getMarginTop());     System.out.println(section.getMarginBottom());     System.out.println(section.getPageHeight());     System.out.println(section.text());   }  }   /**  * 插入內(nèi)容到Range,這里只會寫到內(nèi)存中  * @param range  */  private void insertInfo(Range range) {   range.insertAfter("Hello");  } }

2       寫word doc文件

       在使用POI寫word doc文件的時候我們必須要先有一個doc文件才行,因為我們在寫doc文件的時候是通過HWPFDocument來寫的,而HWPFDocument是要依附于一個doc文件的。所以通常的做法是我們先在硬盤上準備好一個內(nèi)容空白的doc文件,然后建立一個基于該空白文件的HWPFDocument。之后我們就可以往HWPFDocument里面新增內(nèi)容了,然后再把它寫入到另外一個doc文件中,這樣就相當于我們使用POI生成了word doc文件。

       在實際應用中,我們在生成word文件的時候都是生成某一類文件,該類文件的格式是固定的,只是某些字段不一樣罷了。所以在實際應用中,我們大可不必將整個word文件的內(nèi)容都通過HWPFDocument生成。而是先在磁盤上新建一個word文檔,其內(nèi)容就是我們需要生成的word文件的內(nèi)容,然后把里面一些屬于變量的內(nèi)容使用類似于“${paramName}”這樣的方式代替。這樣我們在基于某些信息生成word文件的時候,只需要獲取基于該word文件的HWPFDocument,然后調(diào)用Range的replaceText()方法把對應的變量替換為對應的值即可,之后再把當前的HWPFDocument寫入到新的輸出流中。這種方式在實際應用中用的比較多,因為它不但可以減少我們的工作量,還可以讓文本的格式更加的清晰。下面我們就來基于這種方式做一個示例。

       假設我們現(xiàn)在擁有一些變動的信息,然后需要通過這些信息生成如下格式的word doc文件:

 

        那么根據(jù)上面的描述,首先第一步,我們建立一個對應格式的doc文件作為模板,其內(nèi)容是這樣的:

 

        有了這樣一個模板之后,我們就可以建立對應的HWPFDocument,然后替換對應的變量為相應的值,再把HWPFDocument輸出到對應的輸出流即可。下面是對應的代碼。

public class HwpfTest {   @Test  public void testWrite() throws Exception {   String templatePath = "D://word//template.doc";   InputStream is = new FileInputStream(templatePath);   HWPFDocument doc = new HWPFDocument(is);   Range range = doc.getRange();   //把range范圍內(nèi)的${reportDate}替換為當前的日期   range.replaceText("${reportDate}", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));   range.replaceText("${appleAmt}", "100.00");   range.replaceText("${bananaAmt}", "200.00");   range.replaceText("${totalAmt}", "300.00");   OutputStream os = new FileOutputStream("D://word//write.doc");   //把doc輸出到輸出流中   doc.write(os);   this.closeStream(os);   this.closeStream(is);  }   /**  * 關閉輸入流  * @param is  */  private void closeStream(InputStream is) {   if (is != null) {     try {      is.close();     } catch (IOException e) {      e.printStackTrace();     }   }  }   /**  * 關閉輸出流  * @param os  */  private void closeStream(OutputStream os) {   if (os != null) {     try {      os.close();     } catch (IOException e) {      e.printStackTrace();     }   }  }  } 

(注:本文是基于poi3.9所寫)

 感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 德安县| 西畴县| 潞西市| 福建省| 新邵县| 蒙城县| 布尔津县| 丹棱县| 阜宁县| 韶山市| 泸定县| 镇原县| 舟曲县| 金堂县| 保靖县| 临朐县| 喀什市| 灵山县| 长汀县| 乐业县| 隆昌县| 常州市| 栾城县| 安丘市| 青河县| 永清县| 克东县| 民县| 阳西县| 天等县| 修武县| 南和县| 禄劝| 唐山市| 张家界市| 柞水县| 喀什市| 柞水县| 宜川县| 马关县| 开封县|