简单使用POI对word进行基本导出(段落、表格)
使用场景
最近遇到帮同事做一个多选运动员选择几个运动员就导出几个运动员生成表格,同时还要输出固定文字的word的这样一个功能。我公司一般导出功能都是导出Excel,导出word功能也一般差不多都是使用特定字符串进行替换,没有类似这次这样的需求,在开始百度了一两天后,搜索到的基本上都是已经写好,而且不一定用的了一些代码,而且大部分都没注释,新手看起来及其痛苦,在痛苦了一天半后,我决定重头开始学习POI所以也有了这篇文章。
效果展示
使用步骤
一、插入依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>3.17</version>
</dependency>
二、编写代码
第一步是先创建word文档对象,它是POI对word进行操作的必经之路。
//创建word文档对象
XWPFDocument document = new XWPFDocument();
创建好word文档对象才能开始接下来的步骤
第二步使用文档对象进行创建标题等操作
//这行代码是创建标题
XWPFParagraph title = document.createParagraph();
设置段落
//设置段落居中
title.setAlignment(ParagraphAlignment.valueOf(STJc.INT_CENTER));
// //设置段落左对齐
// title.setAlignment(ParagraphAlignment.valueOf(STJc.INT_LEFT));
// //设置段落右对齐
// title.setAlignment(ParagraphAlignment.valueOf(STJc.INT_RIGHT));
开始编写内容
XWPFRun titleRun = title.createRun();
// titleRun.setColor("00000");
titleRun.setFontSize(20);
titleRun.setFontFamily("宋体");
titleRun.setBold(true);
titleRun.setText("浙江省体育局关于拟授予灵运等42人宝藏男孩称号进行公示的通知");
titleRun.addBreak(); //换行
这样差不多就完成了最简单的word导出了。如果还需要新增段落就反复添加以上代码如下。
XWPFRun titleRun = title.createRun();
// titleRun.setColor("00000");
titleRun.setFontSize(20);
titleRun.setFontFamily("宋体");
titleRun.setBold(true);
titleRun.setText("某某省体育局关于拟授予灵运等42人宝藏男孩称号进行公示的通知");
titleRun.addBreak(); //换行
//添加第一个段落
XWPFParagraph paragraph1 = document.createParagraph();
//设置之段落左对齐
paragraph1.setAlignment(ParagraphAlignment.valueOf(STJc.INT_LEFT));
// ---------以上是设置整段的,以下为设置内容
XWPFRun firstRun = paragraph1.createRun();
firstRun.setFontSize(13);
firstRun.setFontFamily("黑体");
firstRun.addTab();
firstRun.setText("各市体育局、各有关训练单位:" +
"根据《运动员技术等级管理办法》的规定,现对拟授予灵运等42人宝藏男孩称号(具体名单见附件)进行公示。公示期为2021年12月28日-2022年1月6日(七个工作日)。");
firstRun.addBreak(); //换行
firstRun.addTab();
firstRun.setText("公示期内,如对上述名单有异议,任何单位和个人均可以电话、书面或其他形式向省体育局机关纪委和体育竞赛处反映问题的,需加盖单位公章;以个人名义反映问题的,需署名或当面反映。");
firstRun.addBreak(); //换行
//添加第二个段落
XWPFParagraph paragraph2 = document.createParagraph();
paragraph2.setAlignment(ParagraphAlignment.valueOf(STJc.INT_CENTER));
// ---------以上是设置整段的,以下为设置内容
XWPFRun firstRun1 = paragraph2.createRun();
firstRun1.setFontSize(17);
firstRun1.setFontFamily("黑体");
firstRun1.addTab();
firstRun1.setText("拟授予宝藏男孩称号人员名单");
以上就是word对段落进行导出的简单操作,以下内容就是POI对表格的基本操作。
POI导出表格其实就是创建表格,设置好表头然后再循坏添加数据,实际项目中根据要导出的对象的集合来循坏即可
一、创建表格
//创建表格的第一步
//9为列数,自行调整
XWPFTable table = document.createTable(1,9);
CTTbl tTbl = table.getCTTbl();
CTTblPr tTblPr = tTbl.getTblPr() == null ? tTbl.addNewTblPr() : tTbl.getTblPr();
CTTblWidth tTblWidth = tTblPr.isSetTblW() ? tTblPr.getTblW() : tTblPr.getTblW();
设置表格宽度
//这个宽度是整个大表格的,不是局部或具体的单独大小,注意
tTblWidth.setW(new BigInteger("10000"));
tTblWidth.setType(STTblWidth.DXA);
设置表头
//设置表头
table.getRow(0).setHeight(500);
setCellText(table.getRow(0).getCell(0),"序号",null,1000);
setCellText(table.getRow(0).getCell(1),"技术等级",null,2000);
setCellText(table.getRow(0).getCell(2),"姓名",null,2000);
setCellText(table.getRow(0).getCell(3),"性别",null,1000);
setCellText(table.getRow(0).getCell(4),"代表单位",null,2000);
setCellText(table.getRow(0).getCell(5),"所在单位",null,2000);
setCellText(table.getRow(0).getCell(6),"项目",null,2000);
setCellText(table.getRow(0).getCell(7),"比赛名称",null,5000);
setCellText(table.getRow(0).getCell(8),"创造成绩",null,2000);
设置表头参数
// 设置表头 参数
private static void setCellText(XWPFTableCell cell, String text, String bgcolor, Integer width){
CTTc ctTc = cell.getCTTc();
CTTcPr ctTcPr = ctTc.addNewTcPr();
ctTcPr.addNewTcW().setW(BigInteger.valueOf(width));
// cell.setColor(bgcolor);
cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
CTTcPr ctPr = ctTc.addNewTcPr();
ctPr.addNewVAlign().setVal(STVerticalJc.CENTER);
cell.setText(text);
}
接下来就是循坏生成表格以及导出对象字段信息,由于代码过于简单、重复,我就不多说,各位哥哥姐姐,把代码看完就懂了,没看明白的话把demo跑起来玩玩也就差不多。
Integer j = 0;
/**
* maxCount不能写0
*/
for (LevelAthleteApplyBean athleteApply : list) {
//这个是在表格的添加,添加到第几行
XWPFTableRow row = table.insertNewTableRow(j+1);
//设置单元格高
row.setHeight(1000);
for (int i = 0; i < 9; i++ ) {
XWPFTableCell cell = row.createCell();
CTTc ctTc = cell.getCTTc();
CTTcPr ctTcPr = ctTc.addNewTcPr();
if(i == 0){
ctTcPr.addNewTcW().setW(BigInteger.valueOf(1000));
cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
cell.setText(i+1+"");
}
if(i == 1){ // 技术等级
ctTcPr.addNewTcW().setW(BigInteger.valueOf(2000));
cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
if(StringUtils.isNotBlank(athleteApply.getLevelName())){
cell.setText(athleteApply.getLevelName());
}else{
cell.setText(null);
}
}
if(i == 2){ // 姓名
ctTcPr.addNewTcW().setW(BigInteger.valueOf(2000));
cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
if (StringUtils.isNotBlank(athleteApply.getTeenName())) {
cell.setText(athleteApply.getTeenName());
}else{
cell.setText(null);
}
}
if(i == 3){ //性别
ctTcPr.addNewTcW().setW(BigInteger.valueOf(1000));
cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
if (StringUtils.isNotBlank(athleteApply.getTeenSex())) {
cell.setText(athleteApply.getTeenSex());
}else{
cell.setText(null);
}
}
if(i == 4){ // 代表单位
ctTcPr.addNewTcW().setW(BigInteger.valueOf(2000));
cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
if (StringUtils.isNotBlank(athleteApply.getRepresentUnit())) {
cell.setText(athleteApply.getRepresentUnit());
}else{
cell.setText(null);
}
}
if(i == 5){ //所在单位
ctTcPr.addNewTcW().setW(BigInteger.valueOf(2000));
cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
if (StringUtils.isNotBlank(athleteApply.getWorkUnit())) {
cell.setText(athleteApply.getWorkUnit());
}else{
cell.setText(null);
}
}
if(i == 6){ // 项目
ctTcPr.addNewTcW().setW(BigInteger.valueOf(2000));
cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
if (StringUtils.isNotBlank(athleteApply.getItemFen())) {
cell.setText(athleteApply.getItemFen());
}else{
cell.setText(null);
}
}
if(i == 7){ // 比赛名称
ctTcPr.addNewTcW().setW(BigInteger.valueOf(5000));
cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
if (StringUtils.isNotBlank(athleteApply.getActName())) {
cell.setText(athleteApply.getActName());
}else{
cell.setText(null);
}
}
if(i == 8){ //创造成绩
ctTcPr.addNewTcW().setW(BigInteger.valueOf(2000));
cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
if (StringUtils.isNotBlank(athleteApply.getGrade())) {
cell.setText(athleteApply.getGrade());
}else{
cell.setText(null);
}
}
}
}
到这POI的代码就差不多了,但还没用IO溜进行输出,以下的代码为word生成与浏览器下载
// 没有路径 就创造路径
File savefile = new File(path);
if (!savefile.exists()) {
savefile.mkdirs();
}
athleteName = path + "一级运动员称号公示" + currentMill + ".docx";
FileOutputStream fos = new FileOutputStream(athleteName);
document.write(fos);
fos.close();
FileUtil.downloadFile(response, athleteName);
注:FileUtil为浏览器下载工具类,代码也丢在下方。
package com.sport.grade_athlete;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
/**
*
* 灵运
* 2021/9/2
*
*/
public class FileUtil {
public static String downloadFile(HttpServletResponse response, String filePath) {
String[] strArray=filePath.split("/");
String filename=strArray[strArray.length-1];
response.setHeader("Access-Control-Expose-Headers","Content-Disposition");
response.setCharacterEncoding("UTF-8");
response.setHeader("content-type", "application/octet-stream");
response.setContentType("application/octet-stream");
try {
response.setHeader("Content-Disposition", "attachment;filename=" + java.net.URLEncoder.encode(filename, "UTF-8"));
} catch (UnsupportedEncodingException e2) {
e2.printStackTrace();
}
byte[] buff = new byte[1024];
BufferedInputStream bis = null;
OutputStream os = null;
try {
os = response.getOutputStream();
bis = new BufferedInputStream(new FileInputStream(new File(filePath)));
int i = bis.read(buff);
while (i != -1) {
os.write(buff, 0, buff.length);
os.flush();
i = bis.read(buff);
}
} catch (FileNotFoundException e1) {
//e1.getMessage()+"系统找不到指定的文件";
return "系统找不到指定的文件";
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return "success";
}
}
文章写到这就结束了,但在多说两句,现在在对word与excel进行导入导出功能时其实使用对POI进行封装的工具可以更简单实现导入导出,这样的工具比如有 esayPOI、esayExcel、或者是hutool。(都有易读的官方使用文档)但也有小伙伴可能跟我一样,因为项目以前大量使用了原生POI来写了很多导入导出功能,导致再使用esayPOI这样的封装框架可能会出现依赖冲突等问题的情况在,所以就写下来这篇文章,时间也不早了,溜了溜了。