Apache poi的hwpf模塊是專門用來對word doc文件進行讀寫操作的。在hwpf裏面我們使用HWPFDocument來表示一個word doc文檔。在HWPFDocument裏面有這麼幾個概念:
l Range:它表示一個範圍,這個範圍可以是整個文檔,也可以是裏面的某一小節(Section),也可以是某一個段落(Paragraph),還可以是擁有共同屬性的一段文本(CharacterRun) 。
l Section:word文檔的一個小節,一個word文檔可以由多個小節構成。
l Paragraph:word文檔的一個段落,一個小節可以由多個段落構成。
l CharacterRun:具有相同屬性的一段文本,一個段落可以由多個CharacterRun組成。
l Table:一個表格。
l TableRow:表格對應的行。
l TableCell:表格對應的單元格。
Section、Paragraph、CharacterRun和Table都繼承自Range。
1 讀word doc文件
在日常應用中,我們從word文件裏面讀取信息的情況非常少見,更多的還是把內容寫入到word文件中。使用POI從word doc文件讀取數據時主要有兩種方式:通過WordExtractor讀和通過HWPFDocument讀。在WordExtractor內部進行信息讀取時還是通過HWPFDocument來獲取的。
1.1 通過WordExtractor讀文件
在使用WordExtractor讀文件時我們只能讀到文件的文本內容和基於文檔的一些屬性,至於文檔內容的屬性等是無法讀到的。如果要讀到文檔內容的屬性則需要使用HWPFDocument來讀取了。下面是使用WordExtractor讀取文件的一個示例:
View Code
1.2 通過HWPFDocument讀文件
HWPFDocument是當前Word文檔的代表,它的功能比WordExtractor要強。通過它我們可以讀取文檔中的表格、列表等,還可以對文檔的內容進行新增、修改和刪除操作。只是在進行完這些新增、修改和刪除後相關信息是保存在HWPFDocument中的,也就是說我們改變的是HWPFDocument,而不是磁盤上的文件。如果要使這些修改生效的話,我們可以調用HWPFDocument的write方法把修改後的HWPFDocument輸出到指定的輸出流中。這可以是原文件的輸出流,也可以是新文件的輸出流(相當於另存爲)或其它輸出流。下面是一個通過HWPFDocument讀文件的示例:
View Code
2 寫word doc文件
在使用POI寫word doc文件的時候我們必須要先有一個doc文件才行,因爲我們在寫doc文件的時候是通過HWPFDocument來寫的,而HWPFDocument是要依附於一個doc文件的。所以通常的做法是我們先在硬盤上準備好一個內容空白的doc文件,然後建立一個基於該空白文件的HWPFDocument。之後我們就可以往HWPFDocument裏面新增內容了,然後再把它寫入到另外一個doc文件中,這樣就相當於我們使用POI生成了word doc文件。
在實際應用中,我們在生成word文件的時候都是生成某一類文件,該類文件的格式是固定的,只是某些字段不一樣罷了。所以在實際應用中,我們大可不必將整個word文件的內容都通過HWPFDocument生成。而是先在磁盤上新建一個word文檔,其內容就是我們需要生成的word文件的內容,然後把裏面一些屬於變量的內容使用類似於“${paramName}”這樣的方式代替。這樣我們在基於某些信息生成word文件的時候,只需要獲取基於該word文件的HWPFDocument,然後調用Range的replaceText()方法把對應的變量替換爲對應的值即可,之後再把當前的HWPFDocument寫入到新的輸出流中。這種方式在實際應用中用的比較多,因爲它不但可以減少我們的工作量,還可以讓文本的格式更加的清晰。下面我們就來基於這種方式做一個示例。
假設我們現在擁有一些變動的信息,然後需要通過這些信息生成如下格式的word doc文件:
那麼根據上面的描述,首先第一步,我們建立一個對應格式的doc文件作爲模板,其內容是這樣的:
有了這樣一個模板之後,我們就可以建立對應的HWPFDocument,然後替換對應的變量爲相應的值,再把HWPFDocument輸出到對應的輸出流即可。下面是對應的代碼 下載地址 。
1 public class HwpfTest { 2 3 @Test 4 public void testWrite() throws Exception { 5 String templatePath = "D:\\word\\template.doc"; 6 InputStream is = new FileInputStream(templatePath); 7 HWPFDocument doc = new HWPFDocument(is); 8 Range range = doc.getRange(); 9 //把range範圍內的${reportDate}替換爲當前的日期 10 range.replaceText("${reportDate}", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));11 range.replaceText("${appleAmt}", "100.00");12 range.replaceText("${bananaAmt}", "200.00");13 range.replaceText("${totalAmt}", "300.00");14 OutputStream os = new FileOutputStream("D:\\word\\write.doc");15 //把doc輸出到輸出流中 16 doc.write(os);17 this.closeStream(os);18 this.closeStream(is);19 }20 21 /** 22 * 關閉輸入流 23 * @param is 24 */ 25 private void closeStream(InputStream is) {26 if (is != null) {27 try {28 is.close();29 } catch (IOException e) {30 e.printStackTrace();31 }32 }33 }34 35 /** 36 * 關閉輸出流 37 * @param os 38 */ 39 private void closeStream(OutputStream os) {40 if (os != null) {41 try {42 os.close();43 } catch (IOException e) {44 e.printStackTrace();45 }46 }47 }48 49 50 }