日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

POI讀寫Word docx文件

系統 2082 0

使用 POI 讀寫 word docx 文件

目錄

1???? docx 文件

1.1???? 通過 XWPFWordExtractor

1.2???? 通過 XWPFDocument

2???? docx 文件

2.1???? 直接通過 XWPFDocument 生成

2.2???? docx 文件作為模板

?

?????? POI 在讀寫 word docx 文件時是通過 xwpf 模塊來進行的,其核心是 XWPFDocument 。一個 XWPFDocument 代表一個 docx 文檔,其可以用來讀 docx 文檔,也可以用來寫 docx 文檔。 XWPFDocument 中主要包含下面這幾種對象:

l ? XWPFParagraph :代表一個段落。

l ? XWPFRun :代表具有相同屬性的一段文本。

l ? XWPFTable :代表一個表格。

l ? XWPFTableRow :表格的一行。

l ? XWPFTableCell :表格對應的一個單元格。

?

1 ?????? docx 文件

?????? 跟讀 doc 文件一樣, POI 在讀 docx 文件的時候也有兩種方式,通過 XWPFWordExtractor 和通過 XWPFDocument 。在 XWPFWordExtractor 讀取信息時其內部還是通過 XWPFDocument 來獲取的。

1.1 ???? 通過 XWPFWordExtractor

?????? 在使用 XWPFWordExtractor 讀取 docx 文檔的內容時,我們只能獲取到其文本,而不能獲取到其文本對應的屬性值。下面是一段使用 XWPFWordExtractor 來讀取 docx 文檔內容的示例代碼:

      public class XwpfTest {
 
   /**
    * 通過XWPFWordExtractor訪問XWPFDocument的內容
    * @throws Exception
    */
   @Test
   public void testReadByExtractor() throws Exception {
      InputStream is = new FileInputStream("D:\\test.docx");
      XWPFDocument doc = new XWPFDocument(is);
      XWPFWordExtractor extractor = new XWPFWordExtractor(doc);
      String text = extractor.getText();
      System.out.println(text);
      CoreProperties coreProps = extractor.getCoreProperties();
      this.printCoreProperties(coreProps);
      this.close(is);
   }
  
   /**
    * 輸出CoreProperties信息
    * @param coreProps
    */
   private void printCoreProperties(CoreProperties coreProps) {
      System.out.println(coreProps.getCategory());   //分類
      System.out.println(coreProps.getCreator()); //創建者
      System.out.println(coreProps.getCreated()); //創建時間
      System.out.println(coreProps.getTitle());   //標題
   }
  
   /**
    * 關閉輸入流
    * @param is
    */
   private void close(InputStream is) {
      if (is != null) {
         try {
            is.close();
         } catch (IOException e) {
            e.printStackTrace();
         }
      }
   }
  
}
    

?

?

1.2 ???? 通過 XWPFDocument

?????? 在通過 XWPFDocument 讀取 docx 文檔時,我們就可以獲取到文本比較精確的屬性信息了。比如我們可以獲取到某一個 XWPFParagraph XWPFRun 或者是某一個 XWPFTable ,包括它們對應的屬性信息。下面是一個使用 XWPFDocument 讀取 docx 文檔的示例:

      public class XwpfTest {
 
   /**
    * 通過XWPFDocument對內容進行訪問。對于XWPF文檔而言,用這種方式進行讀操作更佳。
    * @throws Exception
    */
   @Test
   public void testReadByDoc() throws Exception {
      InputStream is = new FileInputStream("D:\\table.docx");
      XWPFDocument doc = new XWPFDocument(is);
      List<XWPFParagraph> paras = doc.getParagraphs();
      for (XWPFParagraph para : paras) {
         //當前段落的屬性
//       CTPPr pr = para.getCTP().getPPr();
         System.out.println(para.getText());
      }
      //獲取文檔中所有的表格
      List<XWPFTable> tables = doc.getTables();
      List<XWPFTableRow> rows;
      List<XWPFTableCell> cells;
      for (XWPFTable table : tables) {
         //表格屬性
//       CTTblPr pr = table.getCTTbl().getTblPr();
         //獲取表格對應的行
         rows = table.getRows();
         for (XWPFTableRow row : rows) {
            //獲取行對應的單元格
            cells = row.getTableCells();
            for (XWPFTableCell cell : cells) {
                System.out.println(cell.getText());;
            }
         }
      }
      this.close(is);
   }
  
   /**
    * 關閉輸入流
    * @param is
    */
   private void close(InputStream is) {
      if (is != null) {
         try {
            is.close();
         } catch (IOException e) {
            e.printStackTrace();
         }
      }
   }
  
}
    

?

?

2 ?????? docx 文件

2.1 ???? 直接通過 XWPFDocument 生成

?????? 在使用 XWPFDocument docx 文件時不需要像使用 HWPFDocument doc 文件那樣必須從一個 doc 文件開始,我們可以直接 new 一個空的 XWPFDocument ,之后再往這個 XWPFDocument 里面填充內容,然后再把它寫入到對應的輸出流中。下面是使用 XWPFDocument 生成 docx 文件的示例代碼:

      public class XwpfTest {
  
   /**
    * 基本的寫操作
    * @throws Exception
    */
   @Test
   public void testSimpleWrite() throws Exception {
      //新建一個文檔
      XWPFDocument doc = new XWPFDocument();
      //創建一個段落
      XWPFParagraph para = doc.createParagraph();
     
      //一個XWPFRun代表具有相同屬性的一個區域。
      XWPFRun run = para.createRun();
      run.setBold(true); //加粗
      run.setText("加粗的內容");
      run = para.createRun();
      run.setColor("FF0000");
      run.setText("紅色的字。");
      OutputStream os = new FileOutputStream("D:\\simpleWrite.docx");
      //把doc輸出到輸出流
      doc.write(os);
      this.close(os);
   }
  
   /***
    * 寫一個表格
    * @throws Exception
    */
   @Test
   public void testWriteTable() throws Exception {
      XWPFDocument doc = new XWPFDocument();
      //創建一個5行5列的表格
      XWPFTable table = doc.createTable(5, 5);
      //這里增加的列原本初始化創建的那5行在通過getTableCells()方法獲取時獲取不到,但通過row新增的就可以。
//    table.addNewCol(); //給表格增加一列,變成6列
      table.createRow(); //給表格新增一行,變成6行
      List<XWPFTableRow> rows = table.getRows();
      //表格屬性
      CTTblPr tablePr = table.getCTTbl().addNewTblPr();
      //表格寬度
      CTTblWidth width = tablePr.addNewTblW();
      width.setW(BigInteger.valueOf(8000));
      XWPFTableRow row;
      List<XWPFTableCell> cells;
      XWPFTableCell cell;
      int rowSize = rows.size();
      int cellSize;
      for (int i=0; i<rowSize; i++) {
         row = rows.get(i);
         //新增單元格
         row.addNewTableCell();
         //設置行的高度
         row.setHeight(500);
         //行屬性
//       CTTrPr rowPr = row.getCtRow().addNewTrPr();
         //這種方式是可以獲取到新增的cell的。
//       List<CTTc> list = row.getCtRow().getTcList();
         cells = row.getTableCells();
         cellSize = cells.size();
         for (int j=0; j<cellSize; j++) {
            cell = cells.get(j);
            if ((i+j)%2==0) {
                //設置單元格的顏色
                cell.setColor("ff0000"); //紅色
            } else {
                cell.setColor("0000ff"); //藍色
            }
            //單元格屬性
            CTTcPr cellPr = cell.getCTTc().addNewTcPr();
            cellPr.addNewVAlign().setVal(STVerticalJc.CENTER);
            if (j == 3) {
                //設置寬度
                cellPr.addNewTcW().setW(BigInteger.valueOf(3000));
            }
            cell.setText(i + ", " + j);
         }
      }
      //文件不存在時會自動創建
      OutputStream os = new FileOutputStream("D:\\table.docx");
      //寫入文件
      doc.write(os);
      this.close(os);
   }
  
   /**
    * 關閉輸出流
    * @param os
    */
   private void close(OutputStream os) {
      if (os != null) {
         try {
            os.close();
         } catch (IOException e) {
            e.printStackTrace();
         }
      }
   }
  
}
    

?

?

2.2 ???? docx 文件作為模板

?????? 當然,我們也可以像寫 doc 文件那樣,先以一個 docx 文件作為模板,然后建立基于該 docx 文件的 XWPFDocument 對象,再把里面一些變化的信息在運行時進行替換,之后將 XWPFDocument 進行輸出就可以了。所不同的是 XWPFDocument 中沒有像 HWPFDocument 中那樣的 Range 可以用來直接替換內容。而且底層的 XWPFParagraph XWPFRun 也不支持直接將文本進行替換。倒是 XWPFRun 提供了一個設置文本的方法,不過新的文本不會替換舊的文本,而是會追加到原來的文本之后。現在的一個做法是先找出含有需要替換的變量的 XWPFRun ,然后將其移除,之后在原來的位置新增一個 XWPFRun ,其對應的文本是替換變量之后的文本。不過你設置的那個的變量的位置不一定就在一個 XWPFRun 里面,它有可能會被拆分到兩個甚至更多的 XWPFRun 中,所以不是很有必要的話還是不推薦使用這種方式。

?????? 假設我們有一個 docx 文件,其內容是這樣的:


POI讀寫Word docx文件

?

?????? 之后我們以該文件作為模板,利用相關數據把里面的變量進行替換,然后把替換后的文檔輸出到另一個 docx 文件中。具體做法如下:

       
public class XwpfTest {
 
   /**
    * 用一個docx文檔作為模板,然后替換其中的內容,再寫入目標文檔中。
    * @throws Exception
    */
   @Test
   public void testTemplateWrite() throws Exception {
      Map<String, Object> params = new HashMap<String, Object>();
      params.put("reportDate", "2014-02-28");
      params.put("appleAmt", "100.00");
      params.put("bananaAmt", "200.00");
      params.put("totalAmt", "300.00");
      String filePath = "D:\\word\\template.docx";
      InputStream is = new FileInputStream(filePath);
      XWPFDocument doc = new XWPFDocument(is);
      //替換段落里面的變量
      this.replaceInPara(doc, params);
      //替換表格里面的變量
      this.replaceInTable(doc, params);
      OutputStream os = new FileOutputStream("D:\\word\\write.docx");
      doc.write(os);
      this.close(os);
      this.close(is);
   }
  
   /**
    * 替換段落里面的變量
    * @param doc 要替換的文檔
    * @param params 參數
    */
   private void replaceInPara(XWPFDocument doc, Map<String, Object> params) {
      Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator();
      XWPFParagraph para;
      while (iterator.hasNext()) {
         para = iterator.next();
         this.replaceInPara(para, params);
      }
   }
  
   /**
    * 替換段落里面的變量
    * @param para 要替換的段落
    * @param params 參數
    */
   private void replaceInPara(XWPFParagraph para, Map<String, Object> params) {
      List<XWPFRun> runs;
      Matcher matcher;
      if (this.matcher(para.getParagraphText()).find()) {
         runs = para.getRuns();
         for (int i=0; i<runs.size(); i++) {
            XWPFRun run = runs.get(i);
            String runText = run.toString();
            matcher = this.matcher(runText);
            if (matcher.find()) {
                while ((matcher = this.matcher(runText)).find()) {
                   runText = matcher.replaceFirst(String.valueOf(params.get(matcher.group(1))));
                }
                //直接調用XWPFRun的setText()方法設置文本時,在底層會重新創建一個XWPFRun,把文本附加在當前文本后面,
                //所以我們不能直接設值,需要先刪除當前run,然后再自己手動插入一個新的run。
                para.removeRun(i);
                para.insertNewRun(i).setText(runText);
            }
         }
      }
   }
  
   /**
    * 替換表格里面的變量
    * @param doc 要替換的文檔
    * @param params 參數
    */
   private void replaceInTable(XWPFDocument doc, Map<String, Object> params) {
      Iterator<XWPFTable> iterator = doc.getTablesIterator();
      XWPFTable table;
      List<XWPFTableRow> rows;
      List<XWPFTableCell> cells;
      List<XWPFParagraph> paras;
      while (iterator.hasNext()) {
         table = iterator.next();
         rows = table.getRows();
         for (XWPFTableRow row : rows) {
            cells = row.getTableCells();
            for (XWPFTableCell cell : cells) {
                paras = cell.getParagraphs();
                for (XWPFParagraph para : paras) {
                   this.replaceInPara(para, params);
                }
            }
         }
      }
   }
  
   /**
    * 正則匹配字符串
    * @param str
    * @return
    */
   private Matcher matcher(String str) {
      Pattern pattern = Pattern.compile("\\$\\{(.+?)\\}", Pattern.CASE_INSENSITIVE);
      Matcher matcher = pattern.matcher(str);
      return matcher;
   }
  
   /**
    * 關閉輸入流
    * @param is
    */
   private void close(InputStream is) {
      if (is != null) {
         try {
            is.close();
         } catch (IOException e) {
            e.printStackTrace();
         }
      }
   }
  
   /**
    * 關閉輸出流
    * @param os
    */
   private void close(OutputStream os) {
      if (os != null) {
         try {
            os.close();
         } catch (IOException e) {
            e.printStackTrace();
         }
      }
   }
  
}
    

?

?

?????? 經過上面的代碼所示的過程處理后,我們替換變量后新輸出來的 docx 文件的內容是這樣的:


POI讀寫Word docx文件

?

?

POI讀寫Word docx文件


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 久治县| 内乡县| 莲花县| 高州市| 新疆| 乐陵市| 鄂托克前旗| 宁河县| 海丰县| 磐石市| 准格尔旗| 剑阁县| 太康县| 同德县| 建宁县| 环江| 禹城市| 连平县| 巴青县| 河北区| 彰化市| 凌源市| 丰县| 乐业县| 县级市| 灵璧县| 吉水县| 安庆市| 余江县| 内黄县| 江西省| 扎兰屯市| 六枝特区| 大理市| 东阿县| 三穗县| 分宜县| 巴南区| 灵丘县| 合江县| 启东市|