关于POI导出excel的功能我在前面的文章已经写过了,POI导出excel的三种方式 , 导出表格数据到excel并下载(HSSFWorkbook版) ,本篇文章主要是将导入导出功能进一步地封装,在项目中使用工具类直接调用即可。下面是工具类的代码:

pom依赖:

     <dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.5-beta6</version>
</dependency> <dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.5-beta6</version>
</dependency> <dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>3.5-beta6</version>
</dependency> <dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-contrib</artifactId>
<version>3.5-beta6</version>
</dependency>

工具类:

package com.wang.demo.excel.util;

import com.wang.demo.excel.annotation.Excel;
import com.wang.demo.excel.dto.ReturnResult;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils; import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern; /**
* Excel相关处理
*/
public class ExcelUtil<T>
{ private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class); public Class<T> clazz; public ExcelUtil(Class<T> clazz)
{
this.clazz = clazz;
}
/**
* 用于将科学计数法式的数字转换为常规数字显示,BigDecimal表示。<br>
* 如:6.913084212242E12 转换成:6940282300075
* @param obj as Object
* @return
*/
public static String decimal2string(Object obj){
BigDecimal big = null;
if(obj==null) return "";
if(obj instanceof Number){
big = new BigDecimal(((Number)obj).doubleValue());
}else{
return obj.toString();
}
return big==null ? "" : big.toPlainString();
}
public List<T> importExcel(String sheetName, InputStream input) throws Exception
{
List<T> list = new ArrayList<T>(); Workbook workbook = WorkbookFactory.create(input);
Sheet sheet = null;
if(StringUtils.isEmpty(sheetName)){
sheet = workbook.getSheetAt(0);
}else{
sheet = workbook.getSheet(sheetName);
}
int rows = sheet.getPhysicalNumberOfRows(); if (rows > 0)
{
// 有数据时才处理 得到类的所有field.
Field[] allFields = clazz.getDeclaredFields();
// 定义一个map用于存放列的序号和field.
List< Field> fieldsMap = new ArrayList<>();
for (int col = 0; col < allFields.length; col++)
{
Field field = allFields[col];
// 将有注解的field存放到map中.
if (field.isAnnotationPresent(Excel.class))
{
// 设置类的私有字段属性可访问.
field.setAccessible(true);
fieldsMap.add(field);
}
}
for (int i = 1; i < rows; i++)
{
// 从第2行开始取数据,默认第一行是表头.
Row row = sheet.getRow(i);
//获取一行所有的单元格的数量
int cellNum = sheet.getRow(0).getPhysicalNumberOfCells();
T entity = null;
for (int j = 0; j < cellNum; j++)
{
Cell cell = row.getCell(j);
if (cell == null)
{
continue;
}
else
{
cell = row.getCell(j);
} String c = null;
if(cell.getCellType()==Cell.CELL_TYPE_NUMERIC)
{
c = decimal2string(cell.getNumericCellValue());
}else c = cell.getStringCellValue();
if (StringUtils.isEmpty(c))
{
continue;
}
c= replaceBlank(c);
// 如果不存在实例则新建.
entity = entity == null ? clazz.newInstance() : entity;
// 从map中得到对应列的field.
Field field = fieldsMap.get(j);
// 取得类型,并根据对象类型设置值.
Class<?> fieldType = field.getType();
// Class<?> fieldType = String.class;
if (String.class == fieldType)
{
field.set(entity, String.valueOf(c));
}
else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType))
{
field.set(entity, Integer.parseInt(c));
}
else if ((Long.TYPE == fieldType) || (Long.class == fieldType))
{
field.set(entity, Long.valueOf(c));
}
else if ((Float.TYPE == fieldType) || (Float.class == fieldType))
{
field.set(entity, Float.valueOf(c));
}
else if ((Short.TYPE == fieldType) || (Short.class == fieldType))
{
field.set(entity, Short.valueOf(c));
}
else if ((Double.TYPE == fieldType) || (Double.class == fieldType))
{
field.set(entity, Double.valueOf(c));
}
else if (Character.TYPE == fieldType)
{
if ((c != null) && (c.length() > 0))
{
field.set(entity, Character.valueOf(c.charAt(0)));
}
}
else if (Date.class == fieldType)
{
if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC)
{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
cell.setCellValue(sdf.format(cell.getNumericCellValue()));
c = sdf.format(cell.getNumericCellValue());
}
else
{
c = cell.getStringCellValue();
}
}
else if (BigDecimal.class == fieldType)
{
c = cell.getStringCellValue();
}
}
if (entity != null)
{
list.add(entity);
}
}
} return list;
} /**
* 导出excel到网络(直接将http)
*
* @param list
* @param sheetName
* @param response
* @return
*/
public void exportExcelToWeb(List<T> list, String sheetName, HttpServletResponse response) {
// 告诉浏览器用什么软件可以打开此文件
response.setContentType("multipart/form-data");
response.setCharacterEncoding("utf-8");
try {
response.setHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode(sheetName + ".xls", "utf-8"));
this.exportExcel(list,sheetName,response.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
} public void download(List<T> list, String sheetName, HttpServletResponse response) throws UnsupportedEncodingException {
// 告诉浏览器用什么软件可以打开此文件
response.setContentType("application/octet-stream");
response.setCharacterEncoding("UTF-8");
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
String fileName =df.format(new Date())+"导出数据";
fileName = URLEncoder.encode(fileName, "UTF-8");
try {
response.addHeader("Content-Disposition", "attachment;filename=" +fileName + ".xls");
this.exportExcel(list,sheetName,response.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
} /**
* 导出excel到指定路径
*
* @param list
* @param sheetName
* @param path
* @return
*/
public ReturnResult exportExcelToPath(List<T> list, String sheetName,String path) {
ReturnResult returnResult = null;
try {
OutputStream out = new FileOutputStream(path);
returnResult = this.exportExcel(list,sheetName,out);
} catch (Exception e) {
e.printStackTrace();
}
return returnResult;
} /**
* 对list数据源将其里面的数据导入到excel表单
*
* 通过制定out,实现导出到磁盘/网络
*
* @param sheetName 工作表的名称
*/
public ReturnResult exportExcel(List<T> list, String sheetName,OutputStream out) {
// 得到所有定义字段
Field[] allFields = clazz.getDeclaredFields();
List<Field> fields = new ArrayList<Field>();
// 得到所有field并存放到一个list中.
for (Field field : allFields) {
if (field.isAnnotationPresent(Excel.class)) {
fields.add(field);
}
} // 产生工作薄对象
HSSFWorkbook workbook = new HSSFWorkbook();
// excel2003中每个sheet中最多有65536行
int sheetSize = 65536;
// 取出一共有多少个sheet.
double sheetNo = Math.ceil(list.size() / sheetSize);
for (int index = 0; index <= sheetNo; index++) {
// 产生工作表对象
HSSFSheet sheet = workbook.createSheet();
if (sheetNo == 0) {
workbook.setSheetName(index, sheetName);
} else {
// 设置工作表的名称.
workbook.setSheetName(index, sheetName + index);
}
HSSFRow row;
HSSFCell cell; // 产生单元格 // 产生一行
row = sheet.createRow(0);
// 写入各个字段的列头名称
for (int i = 0; i < fields.size(); i++) {
Field field = fields.get(i);
Excel attr = field.getAnnotation(Excel.class);
// 创建列
cell = row.createCell(i);
// 设置列中写入内容为String类型
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
HSSFCellStyle cellStyle = workbook.createCellStyle();
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
cellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
if (attr.name().indexOf("注:") >= 0) {
HSSFFont font = workbook.createFont();
font.setColor(HSSFFont.COLOR_RED);
cellStyle.setFont(font);
cellStyle.setFillForegroundColor(HSSFColor.LIGHT_YELLOW.index);
sheet.setColumnWidth(i, 6000);
} else {
HSSFFont font = workbook.createFont();
// 粗体显示
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
// 选择需要用到的字体格式
cellStyle.setFont(font);
cellStyle.setFillForegroundColor(HSSFColor.LIGHT_YELLOW.index); // 设置列宽
sheet.setColumnWidth(i, 3766);
}
cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
cellStyle.setWrapText(true);
cell.setCellStyle(cellStyle); // 写入列名
cell.setCellValue(attr.name()); // 如果设置了提示信息则鼠标放上去提示.
if (!StringUtils.isEmpty(attr.prompt())) {
// 这里默认设了2-101列提示.
setHSSFPrompt(sheet, "", attr.prompt(), 1, 100, i, i);
}
// 如果设置了combo属性则本列只能选择不能输入
if (attr.combo().length > 0) {
// 这里默认设了2-101列只能选择不能输入.
setHSSFValidation(sheet, attr.combo(), 1, 100, i, i);
}
} int startNo = index * sheetSize;
int endNo = Math.min(startNo + sheetSize, list.size());
// 写入各条记录,每条记录对应excel表中的一行
HSSFCellStyle cs = workbook.createCellStyle();
cs.setAlignment(HSSFCellStyle.ALIGN_CENTER);
cs.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
for (int i = startNo; i < endNo; i++) {
row = sheet.createRow(i + 1 - startNo);
// 得到导出对象.
T vo = (T) list.get(i);
for (int j = 0; j < fields.size(); j++) {
// 获得field.
Field field = fields.get(j);
// 设置实体类私有属性可访问
field.setAccessible(true);
Excel attr = field.getAnnotation(Excel.class);
try {
// 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列.
if (attr.isExport()) {
// 创建cell
cell = row.createCell(j);
cell.setCellStyle(cs);
try {
if (String.valueOf(field.get(vo)).length() > 10) {
throw new Exception("长度超过10位就不用转数字了");
}
// 如果可以转成数字则导出为数字类型
BigDecimal bc = new BigDecimal(String.valueOf(field.get(vo)));
cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC);
cell.setCellValue(bc.doubleValue());
} catch (Exception e) {
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
if (vo == null) {
// 如果数据存在就填入,不存在填入空格.
cell.setCellValue("");
} else {
// 如果数据存在就填入,不存在填入空格.
cell.setCellValue(field.get(vo) == null ? "" : String.valueOf(field.get(vo)));
} }
}
}
catch (Exception e) {
log.error("导出Excel失败{}", e.getMessage());
}
}
}
}
try {
String filename = encodingFilename(sheetName);
//OutputStream out = new FileOutputStream(getfile() + filename);
workbook.write(out);
out.close();
ReturnResult returnResult = new ReturnResult();
returnResult.setMsg("filename");
returnResult.setCode(1);
return returnResult;
}
catch (Exception e) {
log.error("关闭flush失败{}", e.getMessage());
ReturnResult returnResult = new ReturnResult();
returnResult.setMsg("导出Excel失败,请联系网站管理员!");
returnResult.setCode(-1);
return returnResult;
}
} /**
* 设置单元格上提示
*
* @param sheet 要设置的sheet.
* @param promptTitle 标题
* @param promptContent 内容
* @param firstRow 开始行
* @param endRow 结束行
* @param firstCol 开始列
* @param endCol 结束列
* @return 设置好的sheet.
*/
public static HSSFSheet setHSSFPrompt(HSSFSheet sheet, String promptTitle, String promptContent, int firstRow,
int endRow, int firstCol, int endCol)
{
// 构造constraint对象
DVConstraint constraint = DVConstraint.createCustomFormulaConstraint("DD1");
// 四个参数分别是:起始行、终止行、起始列、终止列
CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
// 数据有效性对象
HSSFDataValidation dataValidationView = new HSSFDataValidation(regions, constraint);
dataValidationView.createPromptBox(promptTitle, promptContent);
sheet.addValidationData(dataValidationView);
return sheet;
} /**
* 设置某些列的值只能输入预制的数据,显示下拉框.
*
* @param sheet 要设置的sheet.
* @param textlist 下拉框显示的内容
* @param firstRow 开始行
* @param endRow 结束行
* @param firstCol 开始列
* @param endCol 结束列
* @return 设置好的sheet.
*/
public static HSSFSheet setHSSFValidation(HSSFSheet sheet, String[] textlist, int firstRow, int endRow,
int firstCol, int endCol)
{
// 加载下拉列表内容
DVConstraint constraint = DVConstraint.createExplicitListConstraint(textlist);
// 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列
CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
// 数据有效性对象
HSSFDataValidation dataValidationList = new HSSFDataValidation(regions, constraint);
sheet.addValidationData(dataValidationList);
return sheet;
} /**
* 编码文件名
*/
public String encodingFilename(String filename)
{
filename = UUID.randomUUID().toString() + "_" + filename + ".xls";
return filename;
} public String replaceBlank(String str) {
String dest = "";
if (str!=null) {
Pattern p = Pattern.compile("\\s*|\t|\r|\n");
Matcher m = p.matcher(str);
dest = m.replaceAll("");
}
return dest;
}
}

注解类,用于导出时,列名称的设置

package com.wang.demo.excel.annotation;

import java.lang.annotation.*;

/**
* 自定义导出Excel数据注解
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
public @interface Excel
{
/**
* 导出到Excel中的名字.
*/
public abstract String name(); /**
* 提示信息
*/
public abstract String prompt() default ""; /**
* 设置只能选择不能输入的列内容.
*/
public abstract String[] combo() default {}; /**
* 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写.
*/
public abstract boolean isExport() default true;
}

返回类型,这个可以根据自己需要的自己定义

package com.wang.demo.excel.dto;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map; public class ReturnResult implements Serializable { private static final long serialVersionUID = 6816265515135254415L;
public ReturnResult(){ }
public ReturnResult(int c, String m){
this.code = c;
this.msg = m;
}
public ReturnResult(int c, String m, Map<String, Object> dataMap){
this(c, m);
this.data = dataMap;
}
private Map<String, Object> data;
protected int code = 0;
protected String msg = "";
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Map<String, Object> getData() {
return data;
}
public void setData(Map<String, Object> data) {
this.data = data;
}
public void putAll(Map<String, Object> data){
if(this.data == null) this.data = new HashMap<String, Object>();
this.data.putAll(data);
}
public void put(String key, Object value){
if(this.data == null) this.data = new HashMap<String, Object>();
this.data.put(key, value);
}
}

导出功能

导出数据到excel只需要建一个实体类,使用工具类时,传入实体类的作为泛型,然后给实体类的属性加上@Excel(name="xxx")就可以导出响应的数据了,name是excel的列名称。注意:如果不给属性标上注解,该列就不会被导出到excel。

@RequestMapping("/user/export")
public void exportExcel(HttpServletResponse response){
ExcelUtil<UserDto> excelUtil = new ExcelUtil<>(UserDto.class);
List<UserDto> userDtos = new ArrayList<>();
UserDto userDto1 = new UserDto();
userDto1.setId("aa");
userDto1.setPassword("wang");
userDto1.setUsername("xia");
userDtos.add(userDto1);
excelUtil.exportExcelToWeb(userDtos,"用户信息表",response);
}

实体类:

package com.wang.demo.excel.dto;

import com.wang.demo.excel.annotation.Excel;

public class UserDto {
@Excel(name = "ID")
private String id;
@Excel(name = "用户名")
private String username;
@Excel(name = "密码")
private String password; @Override
public String toString() {
return "UserDto{" +
"id='" + id + '\'' +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
} public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
}
}

导入功能

导入功能的主要目的是获取excel中的数据,使用工具类进行导入也十分方便。只需要接收到前端传过来的file对象,然后使用file获取到InputStream流即可获取到该数据,并根据传入的泛型自动解析成该类。注意:这边的实体类的属性名称要和excel表的属性名称一致,否则会报错。

前端部分

 <form th:action="@{/user/import}" method="post" enctype="multipart/form-data">
<input name ="file" type="file">
<input type="submit" value="上传">
</form>

服务器端

  @RequestMapping("/user/import")
public void importExcel(@RequestParam("file") MultipartFile file){
try {
InputStream inputStream = file.getInputStream();
ExcelUtil<UserDto> excelUtil = new ExcelUtil<>(UserDto.class);
List<UserDto> userDtos = excelUtil.importExcel(null, inputStream);
System.out.println(userDtos.size());
} catch (Exception e) {
e.printStackTrace();
} }

POI导入导出excel(附工具类)的更多相关文章

  1. 使用Apache poi来编写导出excel的工具类

    在JavaWeb开发的需求中,我们会经常看到导出excel的功能需求,然后java并没有提供操作office文档的功能,这个时候我们就需要使用额外的组件来帮助我们完成这项功能了. 很高兴Apache基 ...

  2. Java利用POI导入导出Excel中的数据

         首先谈一下今天发生的一件开心的事,本着一颗android的心我被分配到了PB组,身在曹营心在汉啊!好吧,今天要记录和分享的是Java利用POI导入导出Excel中的数据.下面POI包的下载地 ...

  3. 使用POI插件,提取导出excel的工具类

    在网站的不同的模块都需要使用到导入导出excel的功能,我们就需要写一个通用的工具类ExcelUtil. 我的思路:首先,导入和导出的Excel的文件格式固定:主标题,二级标题,数据行(姑且就这么叫) ...

  4. 导入导出封装的工具类 (一) 利用POI封装

    对于导入导出各个项目中差点儿都会用到,记得在高校平台中封装过导入导出这部分今天看了看是利用JXL封装的而经理说让我用POI写写导出,这两个导入导出框架是眼下比較流程和经常使用的框架,有必要都了解一下. ...

  5. POI导入导出Excel(HSSF格式,User Model方式)

    1.POI说明 Apache POI是Apache软件基金会的开源代码库, POI提供对Microsoft Office格式档案读和写的功能. POI支持的格式: HSSF - 提供读写Microso ...

  6. Java POI导入导出Excel

    1.异常java.lang.NoClassDefFoundError: org/apache/poi/UnsupportedFileFormatException 解决方法: 使用的poi的相关jar ...

  7. java中使用poi导入导出excel文件_并自定义日期格式

    Apache POI项目的使命是创造和保持java API操纵各种文件格式基于Office Open XML标准(OOXML)和微软的OLE复合文档格式(OLE2)2.总之,你可以读写Excel文件使 ...

  8. SpringMvc 使用poi导入导出Excel

    Util类 package com.common.util; public class ExportUtil { private XSSFWorkbook wb = null; private XSS ...

  9. java web 导出Excel 的工具类公用实现

    平时我们在开发后端管理的系统时,经常会出现导出Excel的功能.这个功能很简单,但是呢,我一般就会使用公用的工具类,在一个Util中,暴露公用导出的接口,只需要传入需要导出的数据(一般使用list集合 ...

随机推荐

  1. 【他山之石】mybatis打印sql日志 相关配置

    背景:mybatis的sql日志打印对我来说一直比较迷,哪怕看过网上很多博客后还是这样,这两天刚好又遇到了问题,要查sql不得已又来查阅,这次终于搞定了. mybatis是有提供日志功能支持的,目前支 ...

  2. The Annual Summary Of 2019

    Time is flying, it arrives at the end of year again. This is my first year working in PinDuoDuo inc ...

  3. Linux下安装oracle提示INS-20802 Oracle Net Configuration Assistant

    安装oracle的时候,在最后install过程中,突然弹出INS-20802 :Oracle Net Configuration Assistant 错误. 查了一些资料,也尝试了很多,但是最终尝试 ...

  4. Spring中的ApplicationListener扩展使用

    ApplicationListener是Spring事件机制的一部分,与抽象类ApplicationEvent类配合来完成ApplicationContext的事件机制. 如果容器中存在Applica ...

  5. 源码详解系列(六) ------ 全面讲解druid的使用和源码

    简介 druid是用于创建和管理连接,利用"池"的方式复用连接减少资源开销,和其他数据源一样,也具有连接数控制.连接可靠性测试.连接泄露控制.缓存语句等功能,另外,druid还扩展 ...

  6. 【JDBC】Java程序的数据库初体验

    JDBC是什么 JDBC是一种能够用来执行SQL语句的Java API[接口]. 它是Java提供的一种规范,让各大数据库厂商遵循此规范完成自己的数据库连接驱动[实现接口]. JDBC的入门程序(这里 ...

  7. iOS开发常见问题

    1. 在 ViewController 中添加子视图时,导航栏遮挡添加的子视图 let bpView = BpView.init(frame: CGRect.init(x: , y: , width: ...

  8. 【转】[ppurl]从”皮皮书屋”下载电子书的姿势

    转:http://blog.csdn.net/hcbbt/article/details/42072545 写在前面的扯皮 为什么标题的”皮皮书屋”加上了引号,因为皮皮书屋(http://www.pp ...

  9. 假设检验的Python实现

    结合假设检验的理论知识,本文使用Python对实际数据进行假设检验. 导入测试数据 从线上下载测试数据文件,数据链接:https://pan.baidu.com/s/1t4SKF6U2yyjT365F ...

  10. 【一起学源码-微服务】Feign 源码三:Feign结合Ribbon实现负载均衡的原理分析

    前言 前情回顾 上一讲我们已经知道了Feign的工作原理其实是在项目启动的时候,通过JDK动态代理为每个FeignClinent生成一个动态代理. 动态代理的数据结构是:ReflectiveFeign ...