POI及EasyExcel
POI
操作excel的组件列表:
HSSF : 它被用来读取和写入MS-Excel文件的xls格式。—03版本excel
XSSF : 它是用于MS-Excel中xlsx文件格式。—07版本excel
1. 导入依赖
- 03版本excel,.xls表格文件,最多支持65535行数据
<!--xls 03版本 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.9</version>
</dependency>
- 07版本excel,.xlsx表格文件,不限行数
<!--xls 07版本 xlsx-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.9</version>
</dependency>
2. 对象分析
表格操作会涉及到4个对象:
工作表:WorkBook
工作簿:Sheet
行:Row
单元格(列):Cell
3. 代码操作-写
#### 3.1 写入03版本excel---HSSF
@Test
public void test03() throws IOException {
String path = "V:\\study\\excel\\excel-poi"; //获取项目路径
//创建03版本的xls表格
Workbook workbook = new HSSFWorkbook(); //创建工作表
Sheet sheet = workbook.createSheet("人员统计表"); //创建工作簿
---sheet
Row row = sheet.createRow(0); //创建行,0代表第一行
Cell cell1 = row.createCell(0); //创建列,此处创建了坐标 1,1的单元格
cell1.setCellValue("数量"); //设置单元格的值
Cell cell2 = row.createCell(1); //此处创建坐标1,2的单元格
cell2.setCellValue(10);
//03版本,文件名以xls结尾
FileOutputStream outputStream = new FileOutputStream(path + "人员统计表.xls"); //创建文件输出流
workbook.write(outputStream);
outputStream.close(); //关闭流
System.out.println("表格生成完成");
}
03版本如果一次性写入数据超过65535,会报异常。
3.2 写入07版本excel—XSSF
@Test
public void test07() throws IOException {
String path = "V:\\study\\excel\\excel-poi"; //获取项目路径
//创建07版本的xls表格
Workbook workbook = new XSSFWorkbook();
//创建工作表---sheet
Sheet sheet07 = workbook.createSheet("人员统计表");
//创建行
Row row = sheet07.createRow(0);//第一行
//创建列,此处创建了坐标 1,1的单元格
Cell cell1 = row.createCell(0);
cell1.setCellValue("数量");
//此处创建坐标1,2的单元格
Cell cell2 = row.createCell(1);
cell2.setCellValue(100);
//07版本,文件名以xls结尾
FileOutputStream outputStream = new FileOutputStream(path + "人员统计表.xlsx");
workbook.write(outputStream);
outputStream.close();
System.out.println("表格生成完成");
}
3.3 大数据写07版本—SXSSF
@Test
public void test07Bigdata() throws IOException {
String path = "V:\\study\\excel\\excel-poi"; //获取项目路径
long begin = System.currentTimeMillis();
//创建07版本的xlsx表格,处理大数据
Workbook workbook = new SXSSFWorkbook();
//创建工作表---sheet
Sheet sheet = workbook.createSheet("测试大数据S");
for (int rowNo=0 ;rowNo<100000;rowNo++){
Row row = sheet.createRow(rowNo);
for (int cellNo = 0 ;cellNo<10;cellNo++){
Cell cell = row.createCell(cellNo);
cell.setCellValue(cellNo);
}
}
//07版本,文件名以xlsx结尾
FileOutputStream outputStream = new FileOutputStream(path + " 测试大数据S.xlsx");
workbook.write(outputStream);
outputStream.close();
//使用SXSSF会产生临时文件,需要删除
((SXSSFWorkbook)workbook).dispose();
long end = System.currentTimeMillis();
System.out.println("over");
System.out.println(end - begin);
}
- HSSF,一次性最多写入65535行数据;
- XSSF,一次性可以写入大量数据,但是耗时长;
- SXSSF,XSSF的加速版,大数据写入快(过程中会产生临时文件,需要删除)。
代码操作-读
@Test
public void TestReadCellType() throws IOException {
String path = "V:\\study\\excel\\excel-poi"; //获取项目路径
FileInputStream fileInputStream = new FileInputStream(path+"\\人员信息表.xls");
Workbook workbook = new HSSFWorkbook(fileInputStream);
//获取工作簿
Sheet sheet = workbook.getSheetAt(0);
Row rowTitle = sheet.getRow(0); // 获取第一行,标题行
if(rowTitle!=null){
//获取列数
int cells = rowTitle.getPhysicalNumberOfCells();
for (int cellNo = 0; cellNo <cells ; cellNo++) {
Cell cell = rowTitle.getCell(cellNo);
if(cell!=null){
int cellType = cell.getCellType();
System.out.print("|");
System.out.print(cell.getStringCellValue());
}
}
}
System.out.println();
//读取除标题行外的所有数据
int rows = sheet.getPhysicalNumberOfRows();
for (int rowNo = 1 ; rowNo <rows ; rowNo++) {
Row row = sheet.getRow(rowNo);
if(row!=null){
//获取所有列
int cells = row.getPhysicalNumberOfCells();
for (int cellNo = 0; cellNo <cells; cellNo++) {
Cell cell = row.getCell(cellNo);
int cellType = cell.getCellType();
switch (cellType){
case HSSFCell.CELL_TYPE_STRING://字符串
String value = cell.getStringCellValue();
System.out.println("String:"+value);
break;
case HSSFCell.CELL_TYPE_BOOLEAN://boolean类型
System.out.println("Boolean:"+String.valueOf(cell.getBooleanCellValue()));
break;
case HSSFCell.CELL_TYPE_NUMERIC://数字类型
//数字类型要判断是日期还是数字
if(HSSFDateUtil.isCellDateFormatted(cell)){
System.out.print("日期:");
Date date = cell.getDateCellValue();
System.out.println(new DateTime(date).toString("yyyy-MM-dd HH:mm:ss"));
}else {
//如果是数字,为了防止数字类型过大,先转为字符类型,再获取
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
System.out.println("转为字符串输出"+cell.getStringCellValue());
}
break;
case HSSFCell.CELL_TYPE_ERROR:
System.out.println("数据类型错误");
}
}
}
}
fileInputStream.close();
}
读取操作,需要针对不同的数据类型做判断,用不同的api获取值;
EasyExcel
导入依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.9</version>
</dependency>
代码操作-写
- 创建数据实体类
public class TestData { // 这边全都是标题行
@ExcelProperty("姓名")
private String name;
@ExcelProperty("年龄")
private Integer age;
@ExcelProperty("生日")
private Date birth;
@ExcelIgnore
private String ingore;
}
- 初始化数据
public static List<TestData> data(){
List<TestData> list = new ArrayList<TestData>();
for (int i = 0; i <5 ; i++) {
TestData testData = new TestData();
testData.setName("人员"+i);
testData.setAge(i);
testData.setBirth(new DateTime(new Date()).toDate());
list.add(testData);
}
return list;
}
-
写入数据
@Test public void simpleWrite() throws FileNotFoundException { String path = "V:\\study\\excel"; String fileName = path+"\\easyExcelWrite.xlsx"; //指定用哪个class去写 //write(文件名,格式类) //sheet(工作簿名称) //doWrite(数据) EasyExcel.write(fileName,TestData.class).sheet("人员").doWrite(data()); }
-
执行结果
代码操作-读
-
创建监听器,继承AnalysisEventListener类,重写方法,方法中写逻辑
public class DataDemoListener extends AnalysisEventListener<TestData> { private static final Logger LOGGER = LoggerFactory.getLogger(DataDemoListener.class); /** * 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收 */ private static final int BATCH_COUNT = 5; List<TestData> list = new ArrayList<TestData>(); //解析每一条数据都会执行此方法 public void invoke(TestData testData, AnalysisContext analysisContext) { LOGGER.info("解析到一条数据:{}", JSON.toJSONString(testData)); System.out.println(testData); } //所有数据解析完成了 都会来调用此方法 public void doAfterAllAnalysed(AnalysisContext analysisContext) { System.out.println("解析成功"); } }
-
读取数据,将监听器作为参数传入
@Test public void simpaleRead(){ String path = "V:\\study\\excel"; String fileName = path+"\\easyExcelWrite.xlsx"; // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭 EasyExcel.read(fileName, TestData.class, new DataDemoListener()).sheet().doRead(); }
-
执行结果
参考狂神说java。