博客
关于我
Java导入Excel工具类使用教程
阅读量:671 次
发布时间:2019-03-15

本文共 10686 字,大约阅读时间需要 35 分钟。

前言:

本工具类提供了Excel导入功能,通过反射机制将Excel中数据映射到实体类中,从而获取Excel数据,工具类依赖org.apache.poi包。支持RESTful API,支持Spring MVC中使用。

一.本工具类支持功能:

  • 支持File类型导入
  • 支持MultipartFile类型导入
  • 支持Excel2003及以上版本

二.工具类

所需jar包依赖org.apache.poi版本:

org.apache.poi
poi
4.1.0

本工具类,可直接在项目中使用:

package com.excel.util;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Date;import java.util.List;import java.util.regex.Matcher;import java.util.regex.Pattern;import org.apache.poi.ss.usermodel.Cell;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.ss.usermodel.WorkbookFactory;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.web.multipart.MultipartFile;/** * Excel导入工具类 */public class ImportExcelUtil {    // 正则表达式 ,用于判断是get还是set方法    private static final String REGEX = "[a-zA-Z]";    private static final Logger log = LoggerFactory.getLogger(ImportExcelUtil.class);    /**     * @param multipartFile     * @param startRow      开始行     * @param endRow        结束行(0表示到最后一行结束)     * @param clazz     * @return     * @throws Exception     */    public static List
> importExcelMultipartFile(MultipartFile multipartFile, int startRow, int endRow, Class
clazz) throws Exception { // 判断文件是否存在 if (multipartFile == null || multipartFile.isEmpty()) { throw new IOException("Excel文件内容为空或不存在!"); } String name = "Excel" + System.currentTimeMillis(); File file = File.createTempFile(name, null); multipartFile.transferTo(file); if (!file.exists()) { throw new IOException("文件名为" + file.getName() + "Excel文件不存在!"); } return importExcelFile(file, startRow, endRow, clazz); } /** * 根据文件导入Excel,仅导入数据,去除校验 * * @param file 文件 * @param startRow 开始行,从0开始 * @param endRow 结束行,0表示所有行; 正数表示到第几行结束; 负数表示到倒数第几行结束 * @param clazz sheet需要映射的对象类型 * @return List
< Object>> * @throws Exception */ public static List
> importExcelFile(File file, int startRow, int endRow, Class
clazz) throws Exception { List
> sheetsData = new ArrayList<>(); // 判断文件是否存在 if (!file.exists()) { throw new IOException("文件名为" + file.getName() + "Excel文件不存在!"); } Workbook wb = null; FileInputStream inputStream = null; try { inputStream = new FileInputStream(file); // 工厂模式,根据Excel版本(2003版以前版本,或其他版本),创建对应的工作薄处理类 wb = WorkbookFactory.create(inputStream); for (int sheetNumber = 0; sheetNumber < wb.getNumberOfSheets(); sheetNumber++) { List
rowList = new ArrayList
(); Sheet sheet = wb.getSheetAt(sheetNumber); // 获取最后行号 int lastRowNum = sheet.getLastRowNum(); Row row = null; Pattern p = Pattern.compile("\\s*|\t|\r|\n"); // 循环读取 for (int i = startRow; i <= lastRowNum + endRow; i++) { // 是否全部单元格都为空 boolean isEmptyRow = true; row = sheet.getRow(i); if (row != null) { // 获取每一单元格的值 for (int j = 0; j < row.getLastCellNum(); j++) { String value = p.matcher(getCellValue(row.getCell(j))).replaceAll(""); if (!value.trim().equals("")) { isEmptyRow = false; } } // 校验规则:如果是空白行,没有数据,仅有空格符、制表符等字符(用户无意间输入的字符),则应该过滤掉。 if (!isEmptyRow) { // 该行数据中存在非空单元格,则返回该行 rowList.add(row); } } } sheetsData.add(returnObjectList(rowList, clazz)); } } catch (IOException e) { e.printStackTrace(); } finally { if (wb != null) { wb.close(); } } return sheetsData; } /** * 功能:返回指定的对象集合 */ private static List
returnObjectList(List
rowList, Class
clazz) { List
objectList = null; Object obj = null; String attribute = null; String value = null; int j = 0; try { objectList = new ArrayList(); Field[] declaredFields = clazz.getDeclaredFields(); for (Row row : rowList) { j = 0; obj = clazz.newInstance(); for (Field field : declaredFields) { try { attribute = field.getName().toString(); value = getCellValue(row.getCell(j)); setAttrributeValue(obj, attribute, value.trim()); j++; } catch (Exception e) { log.info("属性映射出错,属性名:" + attribute + "属性值:" + value); e.printStackTrace(); } } // 仅提取没有非空字段的对象 objectList.add(obj); } } catch (Exception e) { e.printStackTrace(); } return objectList; } /** * 功能:获取单元格的值 */ @SuppressWarnings("deprecation") private static String getCellValue(Cell cell) { Object result = ""; if (cell != null) { switch (cell.getCellType()) { case Cell.CELL_TYPE_STRING: result = cell.getStringCellValue(); break; case Cell.CELL_TYPE_NUMERIC: result = cell.getNumericCellValue(); break; case Cell.CELL_TYPE_BOOLEAN: result = cell.getBooleanCellValue(); break; case Cell.CELL_TYPE_FORMULA: result = cell.getCellFormula(); break; case Cell.CELL_TYPE_ERROR: result = cell.getErrorCellValue(); break; case Cell.CELL_TYPE_BLANK: break; default: break; } } return result.toString(); } /** * 功能:给指定对象的指定属性赋值 */ private static void setAttrributeValue(Object obj, String attribute, String value) { if (value == null || value.trim().equals("")) { return; } // 得到该属性的set方法名 String method_name = convertToMethodName(attribute, obj.getClass(), true); Method[] methods = obj.getClass().getMethods(); for (Method method : methods) { /** * 因为这里只是调用bean中属性的set方法,属性名称不能重复 所以set方法也不会重复,所以就直接用方法名称去锁定一个方法 (注:在java中,锁定一个方法的条件是方法名及参数) */ if (method.getName().equals(method_name)) { Class
[] parameterC = method.getParameterTypes(); try { /** * 如果是(整型,浮点型,布尔型,字节型,时间类型), 按照各自的规则把value值转换成各自的类型 否则一律按类型强制转换(比如:String类型) */ if (parameterC[0] == int.class || parameterC[0] == java.lang.Integer.class) { int index = value.lastIndexOf("."); if (index != -1) { value = value.substring(0, index); } try { method.invoke(obj, Integer.valueOf(value)); } catch (Exception e) { System.out.println(value); e.printStackTrace(); } break; } else if (parameterC[0] == float.class || parameterC[0] == java.lang.Float.class) { method.invoke(obj, Float.valueOf(value)); break; } else if (parameterC[0] == double.class || parameterC[0] == java.lang.Double.class) { method.invoke(obj, Double.valueOf(value)); break; } else if (parameterC[0] == byte.class || parameterC[0] == java.lang.Byte.class) { method.invoke(obj, Byte.valueOf(value)); break; } else if (parameterC[0] == boolean.class || parameterC[0] == java.lang.Boolean.class) { method.invoke(obj, Boolean.valueOf(value)); break; } else if (parameterC[0] == java.util.Date.class) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); Date date = null; try { date = sdf.parse(value); } catch (Exception e) { e.printStackTrace(); } method.invoke(obj, date); break; } else { method.invoke(obj, parameterC[0].cast(value)); break; } } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } } } } /** * 功能:根据属性生成对应的set/get方法 */ private static String convertToMethodName(String attribute, Class
objClass, boolean isSet) { /** 通过正则表达式来匹配第一个字符 **/ Pattern p = Pattern.compile(REGEX); Matcher m = p.matcher(attribute); StringBuilder sb = new StringBuilder(); /** 如果是set方法名称 **/ if (isSet) { sb.append("set"); } else { /** get方法名称 **/ try { Field attributeField = objClass.getDeclaredField(attribute); /** 如果类型为boolean **/ if (attributeField.getType() == boolean.class || attributeField.getType() == Boolean.class) { sb.append("is"); } else { sb.append("get"); } } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } } /** 针对以下划线开头的属性 **/ if (attribute.charAt(0) != '_' && m.find()) { sb.append(m.replaceFirst(m.group().toUpperCase())); } else { sb.append(attribute); } return sb.toString(); }}

三.如何使用:

1.导入MultipartFile类型(推荐)

应用场景: Web页面中通过MultipartFile上传文件,可直接转为List<List<Object>>

使用示例:

@PostMapping(value = "/project/import")    public ResultObject importAlarmEvents(@RequestParam MultipartFile file) {      ResultObject result = new ResultObject();        try {            // 从Excel第一行起到最后一行结束,            List
> excelData = ImportExcelUtil.importExcelMultipartFile(file, 1, 0, EventDTO.class); if (excelData == null || excelData.isEmpty()) { result.setMessage("导入失败,Excel内容为空"); return result; } //将Excel中数据,转为你的实体类 List
> alarmList = new ArrayList<>(); for (List
list : excelData) { alarmList.add((List
) list); } Map
res = eventService.importEvent(alarmList); } catch (Exception e) { result.setMessage(e.getMessage()); } return result; }

2.导入文件格式为File

应用场景: Web页面中通过File上传文件,可直接转为List<List<Object>>

使用示例:

@PostMapping(value = "/project/import")    public ResultObject importAlarmEvents(@RequestParam File file) {         ResultObject result = new ResultObject();        try {            // 从Excel第一行起到最后一行结束,            List
> excelData = ImportExcelUtil.importExcelFile(file, 1, 0, EventDTO.class); if (excelData == null || excelData.isEmpty()) { result.setMessage("导入失败,Excel内容为空"); return result; } //将Excel中数据,转为你的实体类 List
> alarmList = new ArrayList<>(); for (List
list : excelData) { alarmList.add((List
) list); } Map
res = eventService.importEvent(alarmList); } catch (Exception e) { result.setMessage(e.getMessage()); } return result; }

实体类示例:

注意:实体类的属性声明顺序,必须跟Excel列头顺序保持一致,否则会出现列数据和属性名对应不上问题

package com.entity.dto;import java.io.Serializable;/** * 数据转Excel对象 注:属性名的顺序和Excel列顺序必须相同 */@SuppressWarnings("serial")public class EventDTO implements Serializable {	// 列字段1	private String name;	// 列字段2	private String code;	public String getName() {		return name;	}	public void setName(String name) {		this.name = name;	}	public String getCode() {		return code;	}	public void setCode(String code) {		this.code = code;	}}

Excel实用教程集锦

以下是我写的关于Java操作Excel的所有教程,基本包含了所有场景。

1.如果简单导出推荐使用工具类的方式,这种配置最简单。

2.如果对导出样式要求极高的还原度,推荐使用Freemarker方式,FreeMarker模板引擎可以通吃所有Excel的导出,属于一劳永逸的方式,项目经常导出推荐使用这种方式。

3.Freemarker导出的Excel为xml格式,是通过重命名为xls后,每次会打开弹框问题,我在《Freemarker整合poi导出带有图片的Excel教程》也已经完美解决,本教程将直接导出真正的xls格式,完美适配新版office和wps。Freemarker是无法导出带有图片的Excel,通过其他技术手段,也在本教程中完美导出带有图片的Excel。

4.下列教程中的代码都经本人和网友多次验证,真实有效!

↓↓↓↓一揽子Excel解决方案,赶快收藏吧↓↓↓↓

转载地址:http://zqfqz.baihongyu.com/

你可能感兴趣的文章
mutiplemap 总结
查看>>
MySQL DELETE 表别名问题
查看>>
MySQL Error Handling in Stored Procedures---转载
查看>>
MVC 区域功能
查看>>
MySQL FEDERATED 提示
查看>>
mysql generic安装_MySQL 5.6 Generic Binary安装与配置_MySQL
查看>>
Mysql group by
查看>>
MySQL I 有福啦,窗口函数大大提高了取数的效率!
查看>>
mysql id自动增长 初始值 Mysql重置auto_increment初始值
查看>>
MySQL in 太多过慢的 3 种解决方案
查看>>
MySQL InnoDB 三大文件日志,看完秒懂
查看>>
Mysql InnoDB 数据更新导致锁表
查看>>
Mysql Innodb 锁机制
查看>>
MySQL InnoDB中意向锁的作用及原理探
查看>>
MySQL InnoDB事务隔离级别与锁机制深入解析
查看>>
Mysql InnoDB存储引擎 —— 数据页
查看>>
Mysql InnoDB存储引擎中的checkpoint技术
查看>>
Mysql InnoDB存储引擎中缓冲池Buffer Pool、Redo Log、Bin Log、Undo Log、Channge Buffer
查看>>
MySQL InnoDB引擎的锁机制详解
查看>>
Mysql INNODB引擎行锁的3种算法 Record Lock Next-Key Lock Grap Lock
查看>>