我不是一个资深高手,只想描述普通人在项目中真正常见的问题,以及我的一些经验!
Apache POI,分别为 Word、Excel、PowerPoint 等各种格式提供不同的类方法,本篇只涉及操作Word文档的功能,对应XWPFDocument类。
可以关注我的专栏《apache poi的那些事情》会持续更新poi的相关内容
话不多说,直接上操作。
1.列举概念
XWPFDocument: 代表一个docx文档,其可以用来读docx文档,也可以用来写docx文档
XWPFParagraph: 代表文档、表格、标题等种的段落,由多个XWPFRun组成
XWPFRun: 代表具有同样风格的一段文本
XWPFTable: 代表一个表格
XWPFTableRow: 代表表格的一行
XWPFTableCell: 代表表格的一个单元格
XWPFPicture: 代表图片
2.基础依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
<exclusions>
<exclusion>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
<version>3.1.0</version>
</dependency>
3.简单使用,按照简单demo讲解
1.段落基础概念:利用如下代码创建文档,并直接将文本写入到空的word中
String targetFilePath = "XXXX/blank.docx";
XWPFDocument document = new XWPFDocument();
File file = new File(targetFilePath);
FileOutputStream os = new FileOutputStream(file);
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
run.setText("hello word!");
document.write(os);
简单做个与其他文章不同的干货,我们要注意到XWPFDocument的结构,结合我列举的类型,要注意文本类的,一定是XWPFParagraph–XWPFRun,在run中才会有实际文本的输入
2.插入表格:利用如下代码创建文档,并插入表格到空的word中
String targetFilePath = "/Users/fanting/temp/poi/word/blank.docx";
XWPFDocument document = new XWPFDocument();
File file = new File(targetFilePath);
FileOutputStream os = new FileOutputStream(file);
XWPFTable table = document.createTable();
// 设置宽度100%
table.setWidth("100%");
//创建表格默认会有第一行 所以后面表格的第一行第一列需要特殊处理
// 所以直接拿到第一行
XWPFTableRow rowOne = table.getRow(0);
// 获取第一个单元格
XWPFTableCell cell = rowOne.getCell(0);
cell.setText("这是第一行第一列");
//创建第一行第二列
rowOne.addNewTableCell().setText("我是第一行第二列");
//创建第二行 会按照之前的格式创建出两个列
XWPFTableRow rowTwo = table.createRow();
rowTwo.getCell(0).setText("第二行第一列");
rowTwo.getCell(1).setText("第二行第二列");
document.write(os);
简单做个与其他文章不同的干货,我们要注意到在word中表格的概念中,基于doc创建table,单元格的概念中才会有设置文本的概念。
3.模拟生成一篇文章内容:利用如下代码创建文档,模拟一篇作文设置基础样式
String targetFilePath = "/Users/fanting/temp/poi/word/blank.docx";
XWPFDocument document = new XWPFDocument();
File file = new File(targetFilePath);
FileOutputStream os = new FileOutputStream(file);
/**
* 第一段 文章标题
* 第二段 文章内容
* 第三段 文章结尾
*/
XWPFParagraph paragraphTitle = document.createParagraph();
// 设置段落居中
paragraphTitle.setAlignment(ParagraphAlignment.CENTER);
XWPFRun runTitle = paragraphTitle.createRun();
// 设置字体加粗
runTitle.setBold(true);
// 设置字体30
runTitle.setFontSize(30);
runTitle.setFontFamily("楷体");
runTitle.setText("文章标题");
XWPFParagraph paragraphContent = document.createParagraph();
// 设置首行缩进
paragraphContent.setIndentationFirstLine(400);// 2个字符 400
XWPFRun runContent = paragraphContent.createRun();
runContent.setFontFamily("华文行楷");
StringBuilder sb = new StringBuilder("");
for (int i = 0; i <50; i++) {
sb.append("文章内容");
}
runContent.setText(sb.toString());
XWPFParagraph paragraphEnd = document.createParagraph();
// 设置首行缩进
paragraphEnd.setIndentationFirstLine(400);// 2个字符 400
XWPFRun runEnd = paragraphEnd.createRun();
runEnd.setText("文章内容");
document.write(os);
简单做个与其他文章不同的干货,我们发现在office得概念中,段落XWPFParagraph设置布局,XWPFRun设置样式,
4.模拟生成课程表,涉及单元格合并等问题
List<String> subjects = new ArrayList<>();
subjects.add("语文");
subjects.add("数学");
subjects.add("英语");
subjects.add("物理");
subjects.add("化学");
subjects.add("生物");
subjects.add("政治");
subjects.add("历史");
subjects.add("物理");
String targetFilePath = "/Users/fanting/temp/poi/word/blank.docx";
XWPFDocument docx = new XWPFDocument();
File file = new File(targetFilePath);
FileOutputStream os = new FileOutputStream(file);
CTDocument1 document = docx.getDocument();
CTBody body = document.getBody();
if(!body.isSetSectPr()){
body.addNewSectPr();
}
CTSectPr sectPr = body.getSectPr();
if(!sectPr.isSetPgSz()){
sectPr.addNewPgSz();
}
// 设置页面大小
CTPageSz pgSz = sectPr.getPgSz();
pgSz.setW(BigInteger.valueOf(18000));
pgSz.setH(BigInteger.valueOf(12000));
pgSz.setOrient(STPageOrientation.LANDSCAPE);
//开始创建标题
XWPFParagraph titleParagraph = docx.createParagraph();
titleParagraph.setAlignment(ParagraphAlignment.CENTER);
XWPFRun titleRun = titleParagraph.createRun();
titleRun.setFontSize(22);
titleRun.setFontFamily("楷体");
titleRun.setColor("000000");
titleRun.setBold(true);
titleRun.setText("高三(28)班课程表");
//创建二级标题
XWPFParagraph secondTitleParagraph = docx.createParagraph();
secondTitleParagraph.setAlignment(ParagraphAlignment.RIGHT);
XWPFRun secondTitleRun = secondTitleParagraph.createRun();
secondTitleRun.setBold(true);
titleRun.setFontFamily("楷体");
secondTitleRun.setFontSize(18);
secondTitleRun.setText("班主任: 喜欢编程的xxx先生");
//添加换行
secondTitleParagraph.insertNewRun(1).addBreak();
//创建课程表
int totalRow = 8;
int totalCol = 7;
int currentRow = 0;
int currentCol = 0;
// 定义跨行合并的标记(行合并)
CTVMerge startMerge = CTVMerge.Factory.newInstance();
startMerge.setVal(STMerge.RESTART);
CTVMerge endMerge = CTVMerge.Factory.newInstance();
endMerge.setVal(STMerge.CONTINUE);
XWPFTable table = docx.createTable(totalRow, totalCol);
table.setWidth("100%");
//给表格添加样式
CTTblPr tblPr = table.getCTTbl().getTblPr();
CTString tblStyle = tblPr.addNewTblStyle();
tblStyle.setVal("课程表的样式");
List<XWPFTableRow> rows = table.getRows();
for (XWPFTableRow row : rows) {
CTTrPr ctTrPr = row.getCtRow().addNewTrPr();
CTHeight ctHeight = ctTrPr.addNewTrHeight();
if(currentRow==0){
ctHeight.setVal(BigInteger.valueOf(350));
}else {
ctHeight.setVal(BigInteger.valueOf(200));
}
List<XWPFTableCell> cells = row.getTableCells();
for (int i = 0; i < cells.size(); i++) {
XWPFTableCell cell = cells.get(i);
CTTcPr ctTcPr = cell.getCTTc().addNewTcPr();
CTVerticalJc ctVerticalJc = ctTcPr.addNewVAlign();
// 设置单元格居中
ctVerticalJc.setVal(STVerticalJc.CENTER);
XWPFParagraph xwpfParagraph = cell.getParagraphs().get(0);
xwpfParagraph.setAlignment(ParagraphAlignment.CENTER);
XWPFRun run = xwpfParagraph.createRun();
run.setFontFamily("宋体");
run.setFontSize(12);
run.setBold(true);
if(currentRow == 0 && (currentCol==0 || currentCol ==1)){
//将第一行的前两个单元格合并
if(currentCol==0){
run.setText("时间" + "\\" + "星期");
ctTcPr.addNewHMerge().setVal(STMerge.RESTART);
}else{
ctTcPr.addNewHMerge().setVal(STMerge.CONTINUE);
}
}else if(currentRow == 0 && currentCol!=0 && currentCol!=1){
run.setText(handleWeekStr(i));
}else{
if(currentCol == 0 && currentRow < 5){
//合并第一列的 1-4 行
if(currentRow == 1){
run.setFontSize(14);
run.setBold(true);
run.setText("上午");
ctTcPr.setVMerge(startMerge);
}else{
ctTcPr.setVMerge(endMerge);
}
}else if(currentCol == 0 && currentRow >= 5){
if(currentRow == 5){
run.setFontSize(14);
run.setText("下午");
run.setBold(true);
ctTcPr.setVMerge(startMerge);
}else{
ctTcPr.setVMerge(endMerge);
}
}else if(currentCol == 1){
run.setFontSize(12);
run.setText("第" + currentRow + "节");
}else{
run.setFontSize(12);
Random random = new Random();
int randomNum = random.nextInt(subjects.size());
run.setText(subjects.get(randomNum));
}
}
currentCol++;
}
currentCol = 0;
currentRow++;
}
docx.write(os);
public static String handleWeekStr(Integer i){
List<String> weeks = new ArrayList<>();
weeks.add("星期一");
weeks.add("星期二");
weeks.add("星期三");
weeks.add("星期四");
weeks.add("星期五");
return weeks.get(i-2)==null?"":weeks.get(i-2);
}
4.展示最复杂的课程表效果
5.源码地址
https://download.csdn.net/download/qq_19887735/89735141
如果没有积分,但是实际需要的,可以私信我