基于POI的Excel导入导出工具ExcelUtil
时间:2019-01-22
本文章向大家介绍基于POI的Excel导入导出工具ExcelUtil,主要包括基于POI的Excel导入导出工具ExcelUtil使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
关于excel的操作工具网上实在太多,但有两方面原因值得自己写一个:1)简单的导入导出功能的案例大同小异,自己写一个也浪费不了多少时间,2)成熟的git工具类功能过于臃肿,我仅仅需要个导入导出你让我依赖你一个完整的package?
一、核心工具类代码:
package com.roboadvisor.platform.util.excelUtil;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.formula.functions.T;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;
import com.roboadvisor.platform.entity.excelEntity.ExcelFiled;
/**
* excel解析工具
* @author fujian
*
*/
public class ExcelUtil {
/**
* 根据clazz定义的column解析excel文件
* @param excel
* @param clazz
*/
public static <T> List<T> parse(MultipartFile excel, Class<T> clazz) {
try {
File tmpFile = File.createTempFile(excel.getOriginalFilename().substring(0, excel.getOriginalFilename().lastIndexOf(".")), excel.getOriginalFilename().substring(excel.getOriginalFilename().lastIndexOf(".")+1));
excel.transferTo(tmpFile);
Workbook workbook = getWorkBook(tmpFile);
Sheet sheet = workbook.getSheetAt(0);
return parseSheet(sheet, clazz);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
private static Workbook getWorkBook(File file) {
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
if(file.getName().endsWith("xls")) {
return new HSSFWorkbook(fis);
}
if(file.getName().endsWith("xlsx")) {
return new XSSFWorkbook(fis);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
IOUtils.closeQuietly(fis);
}
return null;
}
private static <T> List<T> parseSheet(Sheet sheet, Class<T> clazz) {
List<T> result = new ArrayList<>();
Map<String, Integer> field2ColNum = new HashMap<>();
Field[] fields = clazz.getDeclaredFields();
for(Field field : fields) {
if(!field.isAccessible()) {
field.setAccessible(true);
}
ExcelFiled anno = field.getDeclaredAnnotation(ExcelFiled.class);
if(null != anno) {
field2ColNum.put(field.getName(), anno.columnNum());
}
}
for(int rowNum =1; rowNum<sheet.getLastRowNum(); rowNum++) {
Row row = sheet.getRow(rowNum);
try {
T object = clazz.newInstance();
for(String filedName : field2ColNum.keySet()) {
int cellNum = field2ColNum.get(filedName);
Method method = clazz.getDeclaredMethod("set"+filedName.replaceAll("^\\w", String.valueOf(filedName.charAt(0)).toUpperCase()), String.class);
if(CellType.STRING != row.getCell(cellNum).getCellType()) {
method.invoke(object, String.valueOf(row.getCell(cellNum).getNumericCellValue()).replaceAll("\\.\\d+", ""));
} else {
method.invoke(object, row.getCell(cellNum).getStringCellValue());
}
}
result.add(object);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return result;
}
/**
* 将list中的数据写入excel
* @param list
* @return
*/
public static <T> InputStream exportExcel(List<T> list) {
InputStream excel = null;
if(list.isEmpty()) {
return excel;
}
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet();
Row headerRow = sheet.createRow(0);
Class<?> clazz = list.get(0).getClass();
Map<String, Integer> field2ColNum = new HashMap<>();
Field[] fields = clazz.getDeclaredFields();
for(Field field : fields) {
if(!field.isAccessible()) {
field.setAccessible(true);
}
ExcelFiled anno = field.getDeclaredAnnotation(ExcelFiled.class);
if(null != anno) {
field2ColNum.put(field.getName(), anno.columnNum());
headerRow.createCell(anno.columnNum()).setCellValue(anno.columnName());
}
}
Set<String> fileds = field2ColNum.keySet();
for(int i=0; i<list.size(); i++) {
Row row = sheet.createRow(i+1);
for(String field : fileds) {
try {
Method method = clazz.getDeclaredMethod("get"+field.replaceAll("^\\w", String.valueOf(field.charAt(0)).toUpperCase()));
String object = String.valueOf(method.invoke(list.get(i)));
row.createCell(field2ColNum.get(field)).setCellValue(object);
} catch (Exception e) {
e.printStackTrace();
}
}
}
for(int i=0; i<fields.length; i++) {
sheet.autoSizeColumn(i);
}
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
workbook.write(outputStream);
excel = new ByteArrayInputStream(outputStream.toByteArray());
workbook.close();
return excel;
} catch (Exception e) {
e.printStackTrace();
}
return excel;
}
}
二、与excel中内容对应的实体类上需添加的注解如下:
package com.roboadvisor.platform.entity.excelEntity;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
public class ExcelEntity {
private String poolId;
@ExcelFiled(columnName="基金代码", columnNum=0)
private String securityId;
@ExcelFiled(columnName="基金名称", columnNum=1)
private String secName;
@ExcelFiled(columnName="产品类型", columnNum=2)
private String secType;
}
columnName为列名称,中文名称
columnNum为列数,0-based
三、service层调用excel工具类
package com.roboadvisor.platform.service;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.compress.utils.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.roboadvisor.platform.entity.excelEntity.ExcelEntity;
import com.roboadvisor.platform.mapper.FileImportMapper;
import com.roboadvisor.platform.util.excelUtil.ExcelUtil;
import com.roboadvisor.platform.util.resultEntity.ResultEntity;
import com.roboadvisor.platform.util.resultEntity.ResultStatus;
@Service
public class FileImportService {
@Autowired
private FileImportMapper mapper;
/**
* excel内容导入db
* @param excel
* @return
*/
public ResultEntity<String> importExcel(MultipartFile excel) {
List<ExcelEntity> entities = ExcelUtil.parse(excel, ExcelEntity.class);
mapper.insertList(entities);
return new ResultEntity<>(ResultStatus.OK);
}
/**
* db内容写入excel
* @param entities
* @throws UnsupportedEncodingException
*/
public void exportExcel(HttpServletResponse response) throws UnsupportedEncodingException {
List<ExcelEntity> list = mapper.getFromDB();
InputStream in = ExcelUtil.exportExcel(list);
response.reset();
response.setContentType("multipart/form-data");
response.setCharacterEncoding("UTF-8");
String fielname = URLEncoder.encode("export-excel.xlsx", "UTF-8");
response.setHeader("Content-Disposition", "attachment; filename=" + fielname);
byte[] buffer = new byte[1024];
int length;
try {
while((length = in.read(buffer)) >0) {
response.getOutputStream().write(buffer, 0, length);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(in);
}
}
}
- Spring Boot 设置静态资源访问
- IDEA更换主题
- 用正则表达式给字符串属性值都加上双引号
- Spring Boot修改启动端口
- Packet for query is too large (12238 > 1024). You can change this value
- win10下端口被占用解决办法
- 微信小程序开发教程第九章:微信小程序拍照收纳开发以及删除名片等
- centos 安装sbt
- 微信小程序开发教程第七章:微信小程序编辑名片页面开发
- idea中使用scala运行spark出现Exception in thread "main" java.lang.NoClassDefFoundError: scala/collection/Gen
- 使用JPA中@Query 注解实现update 操作
- 微信小程序开发教程!博卡君第二弹【微信小程序项目结构以及配置】
- WCF浅尝
- 如何将页面设置为微信端才能打开
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 踩坑ThinkPHP5之模型对象返回的数据集如何转为数组
- PHP基础编程之鬼斧神工的正则表达式-正则表达式基本语法+简单实例
- PHP+mysql数据库简单分页实例-sql分页
- PHP基础编程之鬼斧神工的正则表达式-正则表达式初探+常用的正则表达式函数
- php基础编程-php连接mysql数据库-mysqli的简单使用
- (数据科学学习手札91)在Python中妥善使用进度条
- MySQL 数据库表分区.
- RMI 远程方法调用
- MyBatis版本升级导致OffsetDateTime入参解析异常问题复盘
- 我靠(call) ,我的未来(Future)在哪里???
- Flutter中ListView加载图片数据的优化
- Python 实现随机森林预测宽带客户离网(附源数据与代码)
- 嘿,你知道新冠疫情现在什么样了吗?
- 关于双目立体视觉的三大基本算法及发展现状的总结
- 权限维持之打造不一样的映像劫持后门