Apache POI是Apache软件基金会的开源项目,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。
POI从版本4.0.1开始,需要Java 8或更高版本。按照需要导入jar包及相关依赖jar包。官方对架包和API有详细的介绍
poi-xx.jar (excel文件生成需要)
poi-examples-xx.jar(官方示例,开发不需要)
poi-excelant-xx.jar(不需要)
poi-ooxml-xx.jar(excel,word,ppt均需要)
poi-ooxml-schemas-xx.jar(excel需要)
poi-scratchpad-xx.jar(ppt,vsd,word,viso,outlook等需要)
官方地址:https://poi.apache.org/overview.html
API:https://poi.apache.org/apidocs/4.1/
这里POI使用 4.1.2版本,简单实现POI通用导入导出Excel(工具类使用接口对象),针对一个sheet的处理,多个sheet同理
创建Springboot项目,引入POI依赖:
org.apache.poi
poi
4.1.2
org.apache.poi
poi-ooxml
4.1.2
org.apache.poi
poi-ooxml-schemas
4.1.2
建表,这里主键自增
CREATE TABLE `t_poi_entity` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`sex` varchar(255) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`height` double DEFAULT NULL,
`birthday` date DEFAULT NULL,
`intro` text,
`createtime` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
1、POI结构说明
HSSFWorkbook类提供读写 Microsoft Excel XLS 格式的excel功能。
XSSFWorkbook类提供读写 Microsoft Excel OOXML XLSX 格式的excel功能。
2、POI常用类说明
Sheet 工作表是电子表格的中心结构,用户在其中完成大部分电子表格工作。对row,合并拆分单元格,设置列宽,获取画笔,页眉页脚等操作
Row 电子表格中的行。对cell,行高,行索引,行样式等操作
Cell 单元格。单元格可以包含文本、数字、日期、链接和公式等。对单元格内容的类型,内容,cell索引,cell样式等操作
Font 字体。对单元格中内容的字体,大小,颜色,加粗,下划线等操作
CellStyle 单元格样式。对边框,字体,对齐方式,背景色等操作
俩分excel数据差不多
1、controller
@GetMapping("/importExcel")
@ResponseBody
public String importExcel(String filePath) {
File file = new File(filePath);
if (ImportExcelUtil.isExcel(file.getName())) {
String reslut = poiSerivce.importExcel(file);
return "importExcel--" + reslut;
} else {
return "importExcel-- 文件类型与模板不符!";
}
}
2、service
public String importExcel(File file) {
// poi_xlsx.xlsx
String fileName = file.getName();
List dataList = null;
String headData = null;
Workbook workbook = null;
String dateFormat = "yyyy-MM-dd";
try {
if (ImportExcelUtil.isExcel2007(fileName)) {
workbook = new XSSFWorkbook(new FileInputStream(file));
} else if (ImportExcelUtil.isExcel2003(fileName)) {
workbook = new HSSFWorkbook(new FileInputStream(file));
}
if (workbook != null) {
headData = ImportExcelUtil.getExcelHeadData(workbook);
dataList = ImportExcelUtil.getExcelData(workbook, 1, 2, dateFormat);
}
//拿到数据进行数据库操作
System.out.println(headData);
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
Optional.ofNullable(dataList).orElse(new ArrayList<>()).forEach(strArr -> {
PoiEntityDO entity = new PoiEntityDO();
for (int i = 0; i < strArr.length; i++) {
String cellValue = strArr[i];
switch (i) {
case 0:
entity.setName(cellValue);
break;
case 1:
entity.setSex(cellValue);
break;
case 2:
entity.setAge(Integer.valueOf(cellValue));
break;
case 3:
entity.setHeight(Double.valueOf(cellValue));
break;
case 4:
try {
entity.setBirthday(sdf.parse(cellValue));
} catch (ParseException e) {
e.printStackTrace();
}
break;
case 5:
entity.setIntro(cellValue);
break;
default:
break;
}
}
entity.setCreatetime(new Date());
poiEntityDOMapper.insert(entity);
});
return "success";
} catch (Exception e) {
e.printStackTrace();
} finally {
if (workbook != null) {
try {
workbook.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return "false";
}
3、工具类
import org.apache.poi.ss.usermodel.*;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
public class ImportExcelUtil {
private ImportExcelUtil() {};
/**
* 读取Excel表头首行信息
*
* @param workbook
* @return 首行表头信息
*/
public static String getExcelHeadData(Workbook workbook) {
String headValue;
Sheet sheet = workbook.getSheetAt(0);
Row row = sheet.getRow(sheet.getFirstRowNum());
headValue = getCellValue(row.getCell(0), null);
return headValue;
}
/**
* 读取Excel数据
*
* @param workbook
* @param fieldRow - 字段所在行,
* @param dataStartRow - 数据开始行
* @param dateFormat - 日期类型处理的格式
* @return 数据集合
*/
public static List getExcelData(Workbook workbook, int fieldRow, int dataStartRow, String dateFormat) {
List dataList = new ArrayList<>();
Sheet sheet = workbook.getSheetAt(0);
// 获取总行数(不包含合计行)
int rowNum = sheet.getLastRowNum();
// 根据字段的行获取总列数
int colNum = sheet.getRow(fieldRow).getPhysicalNumberOfCells();
// 从数据开始行读取excel数据
for (int i = dataStartRow; i <= rowNum; i++) {
String[] rowArr = new String[colNum];
Row row = sheet.getRow(i);
for (int j = 0; j < colNum; j++) {
Cell cell = row.getCell(j);
rowArr[j] = getCellValue(cell, dateFormat);
}
dataList.add(rowArr);
}
return dataList;
}
/**
* 获取单元格的值,返回String
*
* @param cell
* @param dateFormat 日期的格式
* @return 返回String
*/
private static String getCellValue(Cell cell, String dateFormat) {
String cellValue = null;
if (cell == null) {
return cellValue;
}
SimpleDateFormat sdf = new SimpleDateFormat((dateFormat == null || "".equals(dateFormat.trim()) ? "yyyy-MM-dd" : dateFormat));
DecimalFormat df = new DecimalFormat("#0.####################");
switch (cell.getCellType()) {
case STRING: // 字符串
cellValue = cell.getStringCellValue();
break;
case NUMERIC: // 数值,货币,日期,时间等都是这种格式,在此要进行判断
if (DateUtil.isCellDateFormatted(cell)) {
cellValue = sdf.format(cell.getDateCellValue());
} else {
cellValue = df.format(cell.getNumericCellValue());
}
break;
case BOOLEAN: // Boolean
cellValue = String.valueOf(cell.getBooleanCellValue());
break;
case FORMULA: // 公式
cellValue = String.valueOf(cell.getCellFormula());
break;
case BLANK: // 空值
cellValue = null;
break;
default:
cellValue = "";
break;
}
return cellValue;
}
/**
* 是否是excel
*
* @param filePath 文件名或者文件路径
* @return true-是, fasle-否
*/
public static boolean isExcel(String filePath) {
return filePath.matches("^.+\\.(?i)(xlsx|xls)$");
}
/**
* 是否是2003的excel
*
* @param filePath - 文件名或者文件路径
* @return true-是, fasle-否
*/
public static boolean isExcel2003(String filePath) {
return filePath.matches("^.+\\.(?i)(xls)$");
}
/**
* 是否是2007的excel
*
* @param filePath -文件名或者文件路径
* @return true-是, fasle-否
*/
public static boolean isExcel2007(String filePath) {
// 以任意个字符开头,用.分割,最后的xlsx不区分大小写。
return filePath.matches("^.+\\.(?i)(xlsx)$");
}
}
注意:填充sheet数据时,这里使用 map通过字段名取获取值
1、controller
@RequestMapping(value="/exportXLSX")
public ResponseEntity exportExcel() throws Exception{
String fileName = "导出xlsx数据.xlsx";
HttpHeaders headers = new HttpHeaders();
//下载显示的文件名,并解决中文名称乱码问题
String downloadFileName = new String(fileName.getBytes(StandardCharsets.UTF_8.name()),StandardCharsets.ISO_8859_1.name());
//通知浏览器以attachment(下载方式)打开
headers.setContentDispositionFormData("attachment", downloadFileName);
//applicatin/octet-stream: 二进制流数据(最常见的文件下载)
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
byte[] byteArr = poiSerivce.exportExcel(fileName);
return new ResponseEntity(byteArr, headers, HttpStatus.CREATED);
}
2、service
public byte[] exportExcel(String fileName) {
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
List
3、工具类
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public class ExportExcelUtil {
/**
* 创建表头
*
* @param sheet
* @param style - 表头样式
* @param head - 表头内容
* @param headStartRow - 表头开始行,从0开始
* @param firstRow - 合并开始行
* @param lastRow - 合并结束行
* @param firstCol - 合并开始列
* @param lastCol - 合并结束列
*/
public static void creatSheetHead(Sheet sheet, CellStyle style, String head, int headStartRow, int firstRow, int lastRow, int firstCol, int lastCol) {
Row row = sheet.createRow(headStartRow);
Cell cell = row.createCell(headStartRow);
cell.setCellValue(head);
cell.setCellStyle(style);
sheet.addMergedRegion(new CellRangeAddress(firstRow, lastRow, firstCol, lastCol));
}
/**
* 创建单元格样式 - 默认左对齐
*
* @param workbook
* @param name - 字体名称
* @param bold - 是否加粗
* @param height - 字体大小
* @param color - 字体颜色
* @return
*/
public static CellStyle createCellStyle(Workbook workbook, String name, boolean bold, short height, short color) {
CellStyle style = workbook.createCellStyle();
Font font = workbook.createFont();
font.setFontName(name);
font.setBold(bold);
font.setColor(color);
font.setFontHeightInPoints(height);
//斜体
font.setItalic(false);
style.setFont(font);
return style;
}
/**
* 设置单元格样式 - 对齐方式和边框
*
* @param style
* @param halign - 水平对齐
* @param valign - 垂直对齐
* @param border - true-四边框,false-无边框
* @return
*/
public static CellStyle setCellStyle(CellStyle style, HorizontalAlignment halign, VerticalAlignment valign, boolean border) {
style.setAlignment(halign);
style.setVerticalAlignment(valign);
if (border) {
style.setBorderTop(BorderStyle.THIN);
style.setBorderBottom(BorderStyle.THIN);
style.setBorderLeft(BorderStyle.THIN);
style.setBorderRight(BorderStyle.THIN);
}
return style;
}
/**
* 设置列宽
*
* @param sheet
* @param columnIndex - 从0开始
* @param width - 行宽
* @return
*/
public static void createColumnWidth(Sheet sheet, int columnIndex, int width) {
// 256 * width
sheet.setColumnWidth(columnIndex, 256 * width + 184);
}
/**
* 填充sheet数据,这里使用map通过字段名取获取值
*
* @param sheet
* @param style
* @param rowIndex - 数据开始行,从0开始
* @param dataList - 要填充的数据
* @param fieldNameENArr - 字段的名称
*/
public static void fillSheetData(Sheet sheet, CellStyle style, int rowIndex, List
这里简单做了工具类处理,可以根据业务来改变(查看官网API),主要还是理解POI的结构和常用类。
参考文章:
JAVA POI的使用
Java 中使用POI设置EXCEL单元格格式为文本、小数、百分比、货币、日期、科学计数法和中文大写、单元格边框等
java用POI设置Excel的列宽
JAVA POI自动导出数据和图片到excel
ends~