前言
本文由作者三汪首发于。
前几天发了一篇文章,提供了基于最新POI版本的Excel导出示例,提供了网上各个现有代码版本的deprecated警告的解决方案。今天来提供一个万能的导入导出工具类模板以及相应示例。
工具类的思路和代码骨架folk自素剑步轻尘,我个人基于实际需求对代码进行了重写和优化,并补充完善了代码注释。查看工具类代码已在开源中国上发布:获取代码戳这里。
使用模板只需要将ExcelUtil.java和StringUtil.java复制到你的项目中即可。
【划重点:同步支持xls和xlsx版本。实现导入或者导出都只需要两步操作。】
读取Excel调用步骤:
1.定义需要读取的表头字段和表头对应的属性字段
String keyValue ="手机名称:phoneName,颜色:color,售价:price";
2.读取数据
List
readExcel参数说明:
/**
* readExcel:根据传进来的map集合读取Excel以及model读取Excel文件
*
* @author likaixuan,wolfgy
* @version 1.1 2017年9月18日
* @param fileName
* Excel文件名
* @param inputStream 输入流
* @param map
* 表头和属性的Map集合,其中Map中Key为Excel列的名称,Value为反射类的属性
* @param classPath
* 需要映射的model的路径
* @param rowNumIndex
* 表头所在行数(从1开始,即第一行对应行数1)
* @return List 读取到的数据集合
* @throws Exception
* @since JDK 1.7
*/
导出Excel调用步骤
1.定义需要读取的表头字段和表头对应的属性字段
String keyValue ="手机名称:phoneName,颜色:color,售价:price";
2.导出
ExcelUtil.exportExcel("导出数据",new FileOutputStream("E://testOut.xls"), ExcelUtil.getMap(keyValue), list, "com.lkx.model.PhoneModel", null, null, null);
exportExcel参数说明:
/**
*
*
* Description:Excel导出
*
* @author likaixuan,wolfgy
* @version 1.1 2017年9月18日
* @param titleText 标题栏内容
* @param out 输出流
* @param map 表头和属性的Map集合,其中Map中Key为Excel列的名称,Value为反射类的属性
* @param list 要输出的对象集合
* @param classPath 需要映射的model的路径
* @param titleStyle 标题栏样式。若为null则直接使用默认样式
* @param headStyle 表头样式。若为null则直接使用默认样式
* @param dataStyle 数据行样式。若为null则直接使用默认样式
* @throws Exception
* @since JDK 1.7
* void
*/
下面简单粗暴上项目结构和代码。
有什么意见、见解或疑惑,欢迎留言讨论。
项目结构
util层:ExcelUtil.java,StringUtil.java 实现导入导出Excel的工具类及其依赖的String工具类
web层:AssociationController.java 接口类
service层:StudentService.java 业务类
domain层:Student.java 学生实体
代码展示
ExcelUtil.java
/**
* Project Name:excelutil
* File Name:ExcelUtil.java
* Package Name:com.lkx.util
* Date:2017年6月7日上午9:44:58
* Copyright (c) 2017~2020, [email protected] All Rights Reserved.
*
*/
package com.wolfgy.util;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
public class ExcelUtil implements Serializable{
/**
* serialVersionUID
*/
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = LoggerFactory
.getLogger(ExcelUtil.class);
//设置Excel读取最大行数
private static final int MAX_ROW = 20000;
/**
* getMap:(将传进来的表头和表头对应的属性存进Map集合,表头字段为key,属性为value)
*
* @author likaixuan,wolfgy
* @version 1.1 2017年9月18日
* @param 把传进指定格式的字符串解析到Map中
* 形如: String keyValue = "手机名称:phoneName,颜色:color,售价:price";
* @return Map 转换好的Map集合
* @since JDK 1.7
*/
public static Map getMap(String keyValue) {
Map map = new HashMap<>();
if (keyValue != null) {
String[] str = keyValue.split(",");
for (String element : str) {
String[] str2 = element.split(":");
map.put(str2[0], str2[1]);
}
}
return map;
}
/**
* readExcel:根据传进来的map集合读取Excel以及model读取Excel文件
*
* @author likaixuan,wolfgy
* @version 1.1 2017年9月18日
* @param fileName
* Excel文件名
* @param inputStream 输入流
* @param map
* 表头和属性的Map集合,其中Map中Key为Excel列的名称,Value为反射类的属性
* @param classPath
* 需要映射的model的路径
* @param rowNumIndex
* 表头所在行数(从1开始,即第一行对应行数1)
* @return List 读取到的数据集合
* @throws Exception
* @since JDK 1.7
*/
@SuppressWarnings({ "resource", "unchecked" })
public static List readExcel(String fileName, InputStream inputStream, Map map,
String classPath, int rowNumIndex) throws Exception {
// 返回表头字段名和属性字段名Map集合中键的集合(Excel列的名称集合)
Set keySet = map.keySet();
//反射用
Class> demo = null;
Object obj = null;
List
StringUtil.java
/**
* Project Name:excelutil
* File Name:StringUtil.java
* Package Name:com.lkx.util
* Date:2017年6月7日上午9:47:06
* Copyright (c) 2017~2020, [email protected] All Rights Reserved.
*
*/
package com.wolfgy.util;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* ClassName:StringUtil
* Function: TODO ADD FUNCTION.
* Reason: TODO ADD REASON.
* Date: 2017年6月7日 上午9:47:06
* @author likaixuan
* @version V1.0
* @since JDK 1.7
* @see
*/
public class StringUtil {
/**
* 首字母转小写
*
* @param s
* @return
*/
public static String toLowerCaseFirstOne(String s) {
if (Character.isLowerCase(s.charAt(0))) {
return s;
} else {
return (new StringBuilder())
.append(Character.toLowerCase(s.charAt(0)))
.append(s.substring(1)).toString();
}
}
/**
* 首字母转大写
*
* @param s
* @return
*/
public static String toUpperCaseFirstOne(String s) {
if (Character.isUpperCase(s.charAt(0))) {
return s;
} else {
return (new StringBuilder())
.append(Character.toUpperCase(s.charAt(0)))
.append(s.substring(1)).toString();
}
}
/**
* replace:(替换字符串函数)
*
* @param strSource
* 源字符串
* @param strFrom
* 要替换的子串
* @param strTo
* 替换为的字符串
* @return
* @since JDK 1.7
*/
public static String replace(String strSource, String strFrom,
String strTo) {
// 如果要替换的子串为空,则直接返回源串
if (strFrom == null || strFrom.equals(""))
return strSource;
String strDest = "";
// 要替换的子串长度
int intFromLen = strFrom.length();
int intPos;
// 循环替换字符串
while ((intPos = strSource.indexOf(strFrom)) != -1) {
// 获取匹配字符串的左边子串
strDest = strDest + strSource.substring(0, intPos);
// 加上替换后的子串
strDest = strDest + strTo;
// 修改源串为匹配子串后的子串
strSource = strSource.substring(intPos + intFromLen);
}
// 加上没有匹配的子串
strDest = strDest + strSource;
// 返回
return strDest;
}
/**
* String类型日期转为Date类型
*
* @param dateStr
* @return
* @throws ParseException
* @throws Exception
*/
public static Date dateConvertFormat(String dateStr) throws ParseException {
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
date = format.parse(dateStr);
return date;
}
}
Student.java
package com.wolfgy.domain;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.annotations.GenericGenerator;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Entity
@NoArgsConstructor
@Getter
@Setter
public class Student implements Serializable{
/**
* @fields serialVersionUID
*/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(generator = "idGenerator")
@GenericGenerator(name = "idGenerator", strategy = "uuid")
private String id;
private String sName;
}
StudentService.java
//其余代码略,只贴出导入导出相关方法
@Override
public void exportExcel(String[] ids, OutputStream out) {
String keyValue="学生ID:id,学生姓名:sName";
List list = new ArrayList<>();
for (int i = 0; i < ids.length; i++) {
Student student = repository.findOne(ids[i]);
list.add(student);
}
try {
ExcelUtil.exportExcel("学生数据导出", out, ExcelUtil.getMap(keyValue), list, "com.wolfgy.domain.Student", null, null, null);
logger.info("导出成功!");
} catch (Exception e) {
e.printStackTrace();
logger.info("导出失败!");
}
}
@Override
public void importExcel(String fileName,InputStream in) {
logger.info("导入"+fileName+"开始");
String keyValue="学生ID:id,学生姓名:sName";
List list = null;
try {
//readExcel参数列表
//fileName Excel文件名
//inputStream 输入流
//map 表头和属性的Map集合,其中Map中Key为Excel列的名称,Value为反射类的属性
//classPath 需要映射的model的路径
//rowNumIndex 表头所在行数
list = ExcelUtil.readExcel("student.xlsx",in,ExcelUtil.getMap(keyValue),
"com.wolfgy.domain.Student",1);
logger.info(" 导入成功!");
} catch (Exception e) {
logger.error("导入失败!");
}
for (Student student : list) {
logger.info("-------------");
logger.info("name:"+student.getSName());
}
logger.info(" 导入结束!");
}
AssociationController.java
//其余代码略,只贴出导入导出相关方法
@RequestMapping(value = "/student/export" , method = RequestMethod.GET)
public void exporMemberFormExcel(@RequestParam(value = "ids", defaultValue = "", required = false) String[] ids, HttpServletResponse res) throws IOException {
logger.info("---------------导出列表到Excel--------------------");
res.setContentType("application/msexcel;charset=UTF-8");
res.addHeader("Content-Disposition", "attachment;filename=members.xls");
OutputStream out = res.getOutputStream();
studentService.exportExcel(ids, out);
}
@RequestMapping(value="/studen/ajaxUpload.do",method=RequestMethod.POST)
public void ajaxUploadExcel(@RequestParam("file") MultipartFile file) throws Exception{
if(!file.isEmpty()){
InputStream in = file.getInputStream();
String fileName = file.getName();
studentService.importExcel(fileName,in);
}else{
throw new BizException("上传失败,因为文件是空的");
}
}
以上。
希望我的文章对你能有所帮助。
我不能保证文中所有说法的百分百正确,但我能保证它们都是我的理解和感悟以及拒绝复制黏贴。
有什么意见、见解或疑惑,欢迎留言讨论。