亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

POI讀寫Word docx文件

系統(tǒng) 2140 0

使用 POI 讀寫 word docx 文件

目錄

1???? docx 文件

1.1???? 通過 XWPFWordExtractor

1.2???? 通過 XWPFDocument

2???? docx 文件

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

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

?

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

l ? XWPFParagraph :代表一個(gè)段落。

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

l ? XWPFTable :代表一個(gè)表格。

l ? XWPFTableRow :表格的一行。

l ? XWPFTableCell :表格對(duì)應(yīng)的一個(gè)單元格。

?

1 ?????? docx 文件

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

1.1 ???? 通過 XWPFWordExtractor

?????? 在使用 XWPFWordExtractor 讀取 docx 文檔的內(nèi)容時(shí),我們只能獲取到其文本,而不能獲取到其文本對(duì)應(yīng)的屬性值。下面是一段使用 XWPFWordExtractor 來讀取 docx 文檔內(nèi)容的示例代碼:

      public class XwpfTest {
 
   /**
    * 通過XWPFWordExtractor訪問XWPFDocument的內(nèi)容
    * @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()); //創(chuàng)建者
      System.out.println(coreProps.getCreated()); //創(chuàng)建時(shí)間
      System.out.println(coreProps.getTitle());   //標(biāo)題
   }
  
   /**
    * 關(guān)閉輸入流
    * @param is
    */
   private void close(InputStream is) {
      if (is != null) {
         try {
            is.close();
         } catch (IOException e) {
            e.printStackTrace();
         }
      }
   }
  
}
    

?

?

1.2 ???? 通過 XWPFDocument

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

      public class XwpfTest {
 
   /**
    * 通過XWPFDocument對(duì)內(nèi)容進(jìn)行訪問。對(duì)于XWPF文檔而言,用這種方式進(jìn)行讀操作更佳。
    * @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) {
         //當(dāng)前段落的屬性
//       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();
         //獲取表格對(duì)應(yīng)的行
         rows = table.getRows();
         for (XWPFTableRow row : rows) {
            //獲取行對(duì)應(yīng)的單元格
            cells = row.getTableCells();
            for (XWPFTableCell cell : cells) {
                System.out.println(cell.getText());;
            }
         }
      }
      this.close(is);
   }
  
   /**
    * 關(guān)閉輸入流
    * @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 文件時(shí)不需要像使用 HWPFDocument doc 文件那樣必須從一個(gè) doc 文件開始,我們可以直接 new 一個(gè)空的 XWPFDocument ,之后再往這個(gè) XWPFDocument 里面填充內(nèi)容,然后再把它寫入到對(duì)應(yīng)的輸出流中。下面是使用 XWPFDocument 生成 docx 文件的示例代碼:

      public class XwpfTest {
  
   /**
    * 基本的寫操作
    * @throws Exception
    */
   @Test
   public void testSimpleWrite() throws Exception {
      //新建一個(gè)文檔
      XWPFDocument doc = new XWPFDocument();
      //創(chuàng)建一個(gè)段落
      XWPFParagraph para = doc.createParagraph();
     
      //一個(gè)XWPFRun代表具有相同屬性的一個(gè)區(qū)域。
      XWPFRun run = para.createRun();
      run.setBold(true); //加粗
      run.setText("加粗的內(nèi)容");
      run = para.createRun();
      run.setColor("FF0000");
      run.setText("紅色的字。");
      OutputStream os = new FileOutputStream("D:\\simpleWrite.docx");
      //把doc輸出到輸出流
      doc.write(os);
      this.close(os);
   }
  
   /***
    * 寫一個(gè)表格
    * @throws Exception
    */
   @Test
   public void testWriteTable() throws Exception {
      XWPFDocument doc = new XWPFDocument();
      //創(chuàng)建一個(gè)5行5列的表格
      XWPFTable table = doc.createTable(5, 5);
      //這里增加的列原本初始化創(chuàng)建的那5行在通過getTableCells()方法獲取時(shí)獲取不到,但通過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();
         //設(shè)置行的高度
         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) {
                //設(shè)置單元格的顏色
                cell.setColor("ff0000"); //紅色
            } else {
                cell.setColor("0000ff"); //藍(lán)色
            }
            //單元格屬性
            CTTcPr cellPr = cell.getCTTc().addNewTcPr();
            cellPr.addNewVAlign().setVal(STVerticalJc.CENTER);
            if (j == 3) {
                //設(shè)置寬度
                cellPr.addNewTcW().setW(BigInteger.valueOf(3000));
            }
            cell.setText(i + ", " + j);
         }
      }
      //文件不存在時(shí)會(huì)自動(dòng)創(chuàng)建
      OutputStream os = new FileOutputStream("D:\\table.docx");
      //寫入文件
      doc.write(os);
      this.close(os);
   }
  
   /**
    * 關(guān)閉輸出流
    * @param os
    */
   private void close(OutputStream os) {
      if (os != null) {
         try {
            os.close();
         } catch (IOException e) {
            e.printStackTrace();
         }
      }
   }
  
}
    

?

?

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

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

?????? 假設(shè)我們有一個(gè) docx 文件,其內(nèi)容是這樣的:


POI讀寫Word docx文件

?

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

       
public class XwpfTest {
 
   /**
    * 用一個(gè)docx文檔作為模板,然后替換其中的內(nèi)容,再寫入目標(biāo)文檔中。
    * @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 參數(shù)
    */
   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 參數(shù)
    */
   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))));
                }
                //直接調(diào)用XWPFRun的setText()方法設(shè)置文本時(shí),在底層會(huì)重新創(chuàng)建一個(gè)XWPFRun,把文本附加在當(dāng)前文本后面,
                //所以我們不能直接設(shè)值,需要先刪除當(dāng)前run,然后再自己手動(dòng)插入一個(gè)新的run。
                para.removeRun(i);
                para.insertNewRun(i).setText(runText);
            }
         }
      }
   }
  
   /**
    * 替換表格里面的變量
    * @param doc 要替換的文檔
    * @param params 參數(shù)
    */
   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;
   }
  
   /**
    * 關(guān)閉輸入流
    * @param is
    */
   private void close(InputStream is) {
      if (is != null) {
         try {
            is.close();
         } catch (IOException e) {
            e.printStackTrace();
         }
      }
   }
  
   /**
    * 關(guān)閉輸出流
    * @param os
    */
   private void close(OutputStream os) {
      if (os != null) {
         try {
            os.close();
         } catch (IOException e) {
            e.printStackTrace();
         }
      }
   }
  
}
    

?

?

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


POI讀寫Word docx文件

?

?

POI讀寫Word docx文件


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

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

【本文對(duì)您有幫助就好】

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

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 一区二区三区日韩精品 | 伊人快播 | xxxxxx国产精品视频 | 国产激情视频在线 | 色综合在 | 国产亚洲精品国产一区 | 中文字暮文字暮 | 精品国产免费观看久久久 | 好好的曰com久久 | 久草精品视频 | 国产亚洲美女精品久久久 | 日韩毛片在线观看 | 久久一区二区免费播放 | 特黄特级a级黄毛片免费观看多人 | 精品伦理| 午夜黄色影院 | 日本在线精品视频 | 日产一二三四五六七区麻豆 | 精品国产_亚洲人成在线高清 | 97精品一区二区三区在线不卡 | 青青在线成人免费视频 | 欧美看片 | 女人18毛片a级 | 啪啪网站色大全免费 | 欧美男女啪啪 | 国产精品剧情原创麻豆国产 | 色综合久久综合 | 午夜影院免费 | 超级乱淫视频aⅴ播放视频 超级乱淫视频播放日韩 | 国产小视频在线观看www | 日本我不卡 | 99热久久只有精品99只有精品 | 成人18毛片 | 日本爽快片100色毛片 | 亚洲国产精品网 | 美国一级毛片免费看成人 | 成人免费观看一区二区 | 皮皮在线精品亚洲 | 成人国产在线看不卡 | 日韩毛片免费 | 爱爱视频免费网址 |