注:有不正确的地方还望大神能够指出,抱拳了 老铁! 参考 API:[链接] 主要参考文章 1:[链接] 主要参考文章 2:[链接] 主要参考文章 3:[链接] 一、基本属性 建议大家使用 office word 来创建文档。(wps 和 word 结构有些不一样) IBodyElement -------------- ..

Java 使用 POI 操作 XWPFDocumen 创建和读取 Office Word 文档基础篇(一)

本贴最后更新于 701 天前,其中的信息可能已经时移世改

注:有不正确的地方还望大神能够指出,抱拳了 老铁!

参考 API:http://poi.apache.org/apidocs/org/apache/poi/xwpf/usermodel/XWPFDocument.html

主要参考文章 1:http://www.cnblogs.com/Springmoon-venn/p/5494602.html

主要参考文章 2:http://elim.iteye.com/blog/2049110

主要参考文章 3:http://doc.okbase.net/oh_Maxy/archive/154764.html

一、基本属性

建议大家使用 office word 来创建文档。(wps 和 word 结构有些不一样)

IBodyElement ------------------- 迭代器(段落和表格)

XWPFComment ------------------- 评论(个人理解应该是批注)

XWPFSDT

XWPFFooter ------------------- 页脚

XWPFFootnotes ------------------- 脚注

XWPFHeader ------------------- 页眉

XWPFHyperlink ------------------- 超链接

XWPFNumbering ------------------- 编号(我也不知是啥...)

XWPFParagraph ------------------- 段落

XWPFPictureData ------------------- 图片

XWPFStyles ------------------- 样式(设置多级标题的时候用)

XWPFTable ------------------- 表格

二、正文段落

一个文档包含多个段落,一个段落包含多个 Runs,一个 Runs 包含多个 Run,Run 是文档的最小单元

获取所有段落:List paragraphs = word.getParagraphs();

获取一个段落中的所有 Runs:List xwpfRuns = xwpfParagraph.getRuns();

获取一个 Runs 中的一个 Run:XWPFRun run = xwpfRuns.get(index);

XWPFRun-- 代表具有相同属性的一段文本

三、正文表格

一个文档包含多个表格,一个表格包含多行,一行包含多列(格),每一格的内容相当于一个完整的文档

获取所有表格:List xwpfTables = doc.getTables();

获取一个表格中的所有行:List xwpfTableRows = xwpfTable.getRows();

获取一行中的所有列:List xwpfTableCells = xwpfTableRow.getTableCells();

获取一格里的内容:List paragraphs = xwpfTableCell.getParagraphs();

之后和正文段落一样

注:

  1. 表格的一格相当于一个完整的 docx 文档,只是没有页眉和页脚。里面可以有表格,使用 xwpfTableCell.getTables() 获取,and so on
  2. 在 poi 文档中段落和表格是完全分开的,如果在两个段落中有一个表格,在 poi 中是没办法确定表格在段落中间的。(当然除非你本来知道了,这句是废话)。只有文档的格式固定,才能正确的得到文档的结构

个人理解:我不能确定表格所处的位置(第一个段落后面 ,还是第二个段落后面...)

3、页眉:

一个文档可以有多个页眉, 页眉里面可以包含段落和表格

获取文档的页眉:List headerList = doc.getHeaderList();

获取页眉里的所有段落:List paras = header.getParagraphs();

获取页眉里的所有表格:List tables = header.getTables();

之后就一样了

四、页脚:

页脚和页眉基本类似,可以获取表示页数的角标

言归正传 ------- 干货:

五、通过 XWPFDocument 读:段落 + 表格

a、获取文档的所有段落

InputStream is = new FileInputStream("D:\table.docx");
XWPFDocument doc = new XWPFDocument(is);
List paras = doc.getParagraphs();

获取段落内容

for (XWPFParagraph para : paras) {// 当前段落的属性 //CTPPr pr = para.getCTP().getPPr();
System.out.println(para.getText());
}

b、获取文档中所有的表格

List tables = doc.getTables();  
List rows;  
List 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());;  
		}  
	}  
}

六、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 rows = table.getRows(); //表格属性 
CTTblPr tablePr = table.getCTTbl().addNewTblPr(); //表格宽度 
CTTblWidth width = tablePr.addNewTblW();  
width.setW(BigInteger.valueOf(8000));  
XWPFTableRow row;  
List cells;  
XWPFTableCell cell; int rowSize = rows.size(); int cellSize; for (int i=0; i) {  
 row = rows.get(i); //新增单元格 
 row.addNewTableCell(); //设置行的高度 
 row.setHeight(500); //行属性 //CTTrPr rowPr = row.getCtRow().addNewTrPr(); //这种方式是可以获取到新增的cell的。 //List list = row.getCtRow().getTcList(); 
 cells = row.getTableCells();  
 cellSize = cells.size(); for (int j=0; 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 params) {  
  List runs;  
  Matcher matcher; if (this.matcher(para.getParagraphText()).find()) {  
	 runs = para.getRuns(); for (int i=0; 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 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);

}

  • POI
    15 引用 • 21 回帖
  • word
    8 引用 • 17 回帖
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    2271 引用 • 7700 回帖 • 922 关注
1 回帖   
请输入回帖内容...
  • lio API  

    大神,受益了