XWPFDocument創建和讀取Office Word文檔基礎篇(一)


注:有不正確的地方還望大神能夠指出,抱拳了 老鐵!
 
主要參考文章2: http://elim.iteye.com/blog/2049110
 
 
建議大家使用office word來創建文檔。(wps和word結構有些不一樣)
 
IBodyElement -------------------迭代器(段落和表格)
XWPFComment -------------------評論(個人理解應該是批注)
XWPFSDT
XWPFFooter -------------------頁腳
XWPFFootnotes -------------------腳注
XWPFHeader -------------------頁眉
XWPFHyperlink -------------------超鏈接
XWPFNumbering -------------------編號(我也不知是啥...)
XWPFParagraph -------------------段落
XWPFPictureData -------------------圖片
XWPFStyles -------------------樣式(設置多級標題的時候用)
XWPFTable -------------------表格
 
1、正文段落
一個文檔包含多個段落,一個段落包含多個Runs,一個Runs包含多個Run,Run是文檔的最小單元
獲取所有段落:List<XWPFParagraph> paragraphs = word.getParagraphs();
獲取一個段落中的所有Runs:List<XWPFRun> xwpfRuns = xwpfParagraph.getRuns();
獲取一個Runs中的一個Run:XWPFRun run = xwpfRuns.get(index);
 
XWPFRun--代表具有相同屬性的一段文本
 
 
2、正文表格
一個文檔包含多個表格,一個表格包含多行,一行包含多列(格),每一格的內容相當於一個完整的文檔
獲取所有表格:List<XWPFTable> xwpfTables = doc.getTables();
獲取一個表格中的所有行:List<XWPFTableRow> xwpfTableRows = xwpfTable.getRows();
獲取一行中的所有列:List<XWPFTableCell> xwpfTableCells = xwpfTableRow.getTableCells();
獲取一格里的內容:List<XWPFParagraph> paragraphs = xwpfTableCell.getParagraphs();
之后和正文段落一樣
 
 
注:
  1. 表格的一格相當於一個完整的docx文檔,只是沒有頁眉和頁腳。里面可以有表格,使用xwpfTableCell.getTables()獲取,and so on
  2. 在poi文檔中段落和表格是完全分開的,如果在兩個段落中有一個表格,在poi中是沒辦法確定表格在段落中間的。(當然除非你本來知道了,這句是廢話)。只有文檔的格式固定,才能正確的得到文檔的結構
 
個人理解:我不能確定表格所處的位置(第一個段落后面 ,還是第二個段落后面...)
 
 
3、頁眉:
一個文檔可以有多個頁眉,頁眉里面可以包含段落和表格
獲取文檔的頁眉:List<XWPFHeader> headerList = doc.getHeaderList();
獲取頁眉里的所有段落:List<XWPFParagraph> paras = header.getParagraphs();
獲取頁眉里的所有表格:List<XWPFTable> tables = header.getTables();
之后就一樣了
4、頁腳:
頁腳和頁眉基本類似,可以獲取表示頁數的角標
 
 
 
言歸正傳-------干貨:
1、通過XWPFDocument讀:段落+表格
 
a、獲取文檔的所有段落
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());  
} 

 

 
 
b、獲取文檔中所有的表格  
 
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());;  
        }  
    }  
}

 

 
2、XWPFDocument生成word
 
直接new一個空的XWPFDocument,之后再往這個XWPFDocument里面填充內容,然后再把它寫入到對應的輸出流中。
 
新建一個文檔
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);

 

 
 
新建一個表格
//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 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);  
        }  
     }  
  }  
}   

 

 
直接調用XWPFRun的setText()方法設置文本時,在底層會重新創建一個XWPFRun,把文本附加在當前文本后面,所以我們不能直接設值,需要先刪除當前run,然后再自己手動插入一個新的run。
 
 
//抽取 word docx文件中的圖片
String path ="D://abc.docx";  
File file = new File(path);  
try {  
  FileInputStream fis = new FileInputStream(file);  
  XWPFDocument document = new XWPFDocument(fis);  
  XWPFWordExtractor xwpfWordExtractor = new XWPFWordExtractor(document);  
  String text = xwpfWordExtractor.getText();  
  System.out.println(text);  
  List<XWPFPictureData> picList = document.getAllPictures();  
  for (XWPFPictureData pic : picList) {  
    System.out.println(pic.getPictureType() + file.separator + pic.suggestFileExtension()  
        +file.separator+pic.getFileName());  
    byte[] bytev = pic.getData();  
    FileOutputStream fos = new FileOutputStream("D:\\abc\\docxImage\\"+pic.getFileName());   
    fos.write(bytev);  
  }  
  fis.close();  
} catch (IOException e) {  
  e.printStackTrace();  
}  
}  

 

 
 
多級標題結構
/**
 * 自定義樣式方式寫word,參考statckoverflow的源碼
 * 
 * @throws IOException
 */
public static void writeSimpleDocxFile() throws IOException {
    XWPFDocument docxDocument = new XWPFDocument();

    // 老外自定義了一個名字,中文版的最好還是按照word給的標題名來,否則級別上可能會亂
    addCustomHeadingStyle(docxDocument, "標題 1", 1);
    addCustomHeadingStyle(docxDocument, "標題 2", 2);

    // 標題1
    XWPFParagraph paragraph = docxDocument.createParagraph();
    XWPFRun run = paragraph.createRun();
    run.setText("標題 1");
    paragraph.setStyle("標題 1"); // 標題2
    XWPFParagraph paragraph2 = docxDocument.createParagraph();
    XWPFRun run2 = paragraph2.createRun();
    run2.setText("標題 2");
    paragraph2.setStyle("標題 2"); // 正文
    XWPFParagraph paragraphX = docxDocument.createParagraph();
    XWPFRun runX = paragraphX.createRun();
    runX.setText("正文");
// word寫入到文件 FileOutputStream fos = new FileOutputStream("D:/myDoc2.docx"); docxDocument.write(fos); fos.close(); } /** * 增加自定義標題樣式。這里用的是stackoverflow的源碼 * * @param docxDocument 目標文檔 * @param strStyleId 樣式名稱 * @param headingLevel 樣式級別 */ private static void addCustomHeadingStyle(XWPFDocument docxDocument, String strStyleId, int headingLevel) { CTStyle ctStyle = CTStyle.Factory.newInstance(); ctStyle.setStyleId(strStyleId); CTString styleName = CTString.Factory.newInstance(); styleName.setVal(strStyleId); ctStyle.setName(styleName); CTDecimalNumber indentNumber = CTDecimalNumber.Factory.newInstance(); indentNumber.setVal(BigInteger.valueOf(headingLevel)); // lower number > style is more prominent in the formats bar ctStyle.setUiPriority(indentNumber); CTOnOff onoffnull = CTOnOff.Factory.newInstance(); ctStyle.setUnhideWhenUsed(onoffnull); // style shows up in the formats bar ctStyle.setQFormat(onoffnull); // style defines a heading of the given level CTPPr ppr = CTPPr.Factory.newInstance(); ppr.setOutlineLvl(indentNumber); ctStyle.setPPr(ppr); XWPFStyle style = new XWPFStyle(ctStyle); // is a null op if already defined XWPFStyles styles = docxDocument.createStyles(); style.setType(STStyleType.PARAGRAPH); styles.addStyle(style); }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM