Commit 1170aa2f by ypenglv
2 parents 62a31463 7ff5739c
package org.nafmii.admin.user.controller;
import com.alibaba.excel.EasyExcel;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.nafmii.admin.user.dto.ImportExcelDto;
import org.nafmii.admin.user.service.IImportExcelService;
import org.nafmii.common.response.ApiResponse;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.util.List;
@RestController
@RequestMapping("/nafmii/admin/import")
@Api(tags = "3.0.0", description = "中心端批量导入Excel接口")
public class ImportExcelController {
@Resource
private IImportExcelService iImportExcelService;
@ApiOperation( value = "中心端批量导入Excel",notes = "中心端批量导入Excel")
@PostMapping("/batchImportExcel")
@ResponseBody
public ApiResponse batchImportExcel(MultipartFile file){
ApiResponse result = iImportExcelService.batchImportExcel(file);
return result;
}
}
package org.nafmii.admin.user.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.nafmii.admin.user.dto.ImportExcelDto;
import org.nafmii.admin.user.entity.CenterUserPO;
import java.util.List;
/**
* <p>
* 中心端-用户表 Mapper 接口
* </p>
*
* @author suncq
* @since 2021-04-27
*/
@Mapper
public interface ImportExcelMapper extends BaseMapper<CenterUserPO> {
/**
* @author:suncq
* @Function:中心端用户登陆
* @date 2021/4/27
* @ClassName:
* @version:
* @remark:
*/
int insertExcelData(ImportExcelDto data);
}
package org.nafmii.admin.user.dto;
import io.swagger.annotations.ApiModel;
import lombok.Data;
@Data
@ApiModel("导入Excel参数对象")
public class ImportExcelDto {
private String column1;
private String column2;
private String column3;
}
package org.nafmii.admin.user.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName("IMPORT_EXCEL_TEST")
@ApiModel(value="导入ExcelPO对象", description="导入excel测试表")
public class ImportExcelPO extends Model {
private String column1;
private String column2;
private String column3;
}
package org.nafmii.admin.user.service;
import org.nafmii.admin.user.dto.ImportExcelDto;
import org.nafmii.common.response.ApiResponse;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
* <p>
* 中心端-用户表 服务类
* </p>
*
* @author suncq
* @since 2021-04-27
*/
public interface IImportExcelService {
/**
* @author:suncq
* @Function:中心端用户登陆
* @date 2021/4/27
* @ClassName:
* @version:
* @remark:
*/
ApiResponse batchImportExcel(MultipartFile file);
}
package org.nafmii.admin.user.service.impl;
import com.alibaba.excel.EasyExcel;
import lombok.extern.slf4j.Slf4j;
import org.nafmii.admin.user.dao.ImportExcelMapper;
import org.nafmii.admin.user.dto.ImportExcelDto;
import org.nafmii.admin.user.service.IImportExcelService;
import org.nafmii.common.response.ApiResponse;
import org.springframework.stereotype.Service;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
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.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.nafmii.admin.user.service.IImportExcelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Resource;
import java.util.List;
/**
* <p>
* 中心端-用户表 服务实现类
* </p>
*
* @author suncq
* @since 2021-04-27
*/
@Slf4j
@Service
public class ImportExcelServiceImpl implements IImportExcelService {
@Resource
private ImportExcelMapper importExcelMapper;
@Override
public ApiResponse batchImportExcel(MultipartFile file) {
List<ImportExcelDto> list = null;
try {
list = EasyExcel.read(file.getInputStream()).sheet(0).head(ImportExcelDto.class).doReadSync();
} catch (IOException e) {
e.printStackTrace();
}
log.info("导入后生成的数据源=============>"+list);
if (!list.isEmpty()) {
for (ImportExcelDto data : list) {
int i = importExcelMapper.insertExcelData(data);
if (i < 0){
return new ApiResponse(ApiResponse.FAIL, ApiResponse.FAIL_TEXT);
}
}
}
return new ApiResponse(ApiResponse.SUCCESS, ApiResponse.SUCCESS_TEXT);
}
public String importExcel(InputStream inputStream, String fileName) throws Exception {
String message = "Import success";
boolean isE2007 = false;
//判断是否是excel2007格式
if (fileName.endsWith("xlsx")) {
isE2007 = true;
}
int rowIndex = 0;
try {
InputStream input = inputStream; //建立输入流
Workbook wb;
//根据文件格式(2003或者2007)来初始化
if (isE2007) {
wb = new XSSFWorkbook(input);
} else {
wb = new HSSFWorkbook(input);
}
Sheet sheet = wb.getSheetAt(0); //获得第一个表单
int rowCount = sheet.getLastRowNum() + 1;
for (int i = 1; i < rowCount; i++) {
rowIndex = i;
Row row;
for (int j = 0; j < 26; j++) {
if (isMergedRegion(sheet, i, j)) {
System.out.print(getMergedRegionValue(sheet, i, j) + "\t");
} else {
row = sheet.getRow(i);
System.out.print(row.getCell(j) + "\t");
}
}
System.out.print("\n");
}
} catch (Exception ex) {
message = "Import failed, please check the data in " + rowIndex + " rows ";
}
return message;
}
/**
* 获取单元格的值
*
* @param cell
* @return
*/
public String getCellValue(Cell cell) {
if (cell == null) return "";
return cell.getStringCellValue();
}
/**
* 合并单元格处理,获取合并行
*
* @param sheet
* @return List<CellRangeAddress>
*/
public List<CellRangeAddress> getCombineCell(Sheet sheet) {
List<CellRangeAddress> list = new ArrayList<>();
//获得一个 sheet 中合并单元格的数量
int sheetmergerCount = sheet.getNumMergedRegions();
//遍历所有的合并单元格
for (int i = 0; i < sheetmergerCount; i++) {
//获得合并单元格保存进list中
CellRangeAddress ca = sheet.getMergedRegion(i);
list.add(ca);
}
return list;
}
private int getRowNum(List<CellRangeAddress> listCombineCell, Cell cell, Sheet sheet) {
int xr = 0;
int firstC = 0;
int lastC = 0;
int firstR = 0;
int lastR = 0;
for (CellRangeAddress ca : listCombineCell) {
//获得合并单元格的起始行, 结束行, 起始列, 结束列
firstC = ca.getFirstColumn();
lastC = ca.getLastColumn();
firstR = ca.getFirstRow();
lastR = ca.getLastRow();
if (cell.getRowIndex() >= firstR && cell.getRowIndex() <= lastR) {
if (cell.getColumnIndex() >= firstC && cell.getColumnIndex() <= lastC) {
xr = lastR;
}
}
}
return xr;
}
/**
* 判断单元格是否为合并单元格,是的话则将单元格的值返回
*
* @param listCombineCell 存放合并单元格的list
* @param cell 需要判断的单元格
* @param sheet sheet
* @return
*/
public String isCombineCell(List<CellRangeAddress> listCombineCell, Cell cell, Sheet sheet)
throws Exception {
int firstC = 0;
int lastC = 0;
int firstR = 0;
int lastR = 0;
String cellValue = null;
for (CellRangeAddress ca : listCombineCell) {
//获得合并单元格的起始行, 结束行, 起始列, 结束列
firstC = ca.getFirstColumn();
lastC = ca.getLastColumn();
firstR = ca.getFirstRow();
lastR = ca.getLastRow();
if (cell.getRowIndex() >= firstR && cell.getRowIndex() <= lastR) {
if (cell.getColumnIndex() >= firstC && cell.getColumnIndex() <= lastC) {
Row fRow = sheet.getRow(firstR);
Cell fCell = fRow.getCell(firstC);
cellValue = getCellValue(fCell);
break;
}
} else {
cellValue = "";
}
}
return cellValue;
}
/**
* 获取合并单元格的值
*
* @param sheet
* @param row
* @param column
* @return
*/
public String getMergedRegionValue(Sheet sheet, int row, int column) {
int sheetMergeCount = sheet.getNumMergedRegions();
for (int i = 0; i < sheetMergeCount; i++) {
CellRangeAddress ca = sheet.getMergedRegion(i);
int firstColumn = ca.getFirstColumn();
int lastColumn = ca.getLastColumn();
int firstRow = ca.getFirstRow();
int lastRow = ca.getLastRow();
if (row >= firstRow && row <= lastRow) {
if (column >= firstColumn && column <= lastColumn) {
Row fRow = sheet.getRow(firstRow);
Cell fCell = fRow.getCell(firstColumn);
return getCellValue(fCell);
}
}
}
return null;
}
/**
* 判断指定的单元格是否是合并单元格
*
* @param sheet
* @param row 行下标
* @param column 列下标
* @return
*/
private boolean isMergedRegion(Sheet sheet, int row, int column) {
int sheetMergeCount = sheet.getNumMergedRegions();
for (int i = 0; i < sheetMergeCount; i++) {
CellRangeAddress range = sheet.getMergedRegion(i);
int firstColumn = range.getFirstColumn();
int lastColumn = range.getLastColumn();
int firstRow = range.getFirstRow();
int lastRow = range.getLastRow();
if (row >= firstRow && row <= lastRow) {
if (column >= firstColumn && column <= lastColumn) {
return true;
}
}
}
return false;
}
}
\ No newline at end of file \ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.nafmii.admin.user.dao.ImportExcelMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="org.nafmii.admin.user.entity.ImportExcelPO">
<result column="COLUMN1" property="column1" />
<result column="COLUMN2" property="column2" />
<result column="COLUMN3" property="column3" />
</resultMap>
<insert id ="insertExcelData" parameterType="org.nafmii.admin.user.dto.ImportExcelDto" >
insert into IMPORT_EXCEL_TEST
(COLUMN1,COLUMN2,COLUMN3)
values(#{column1},
#{column2},
#{column3})
</insert >
</mapper>
...@@ -154,24 +154,23 @@ ...@@ -154,24 +154,23 @@
<dependency> <dependency>
<groupId>org.apache.poi</groupId> <groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId> <artifactId>poi</artifactId>
<version>3.9</version> <version>3.17</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.poi</groupId> <groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId> <artifactId>poi-ooxml</artifactId>
<version>3.9</version> <version>3.17</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.6</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>javax.cache</groupId> <groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId> <artifactId>cache-api</artifactId>
<version>1.1.0</version> <version>1.1.0</version>
</dependency> </dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.6</version>
</dependency>
<dependency> <dependency>
<groupId>com.google.guava</groupId> <groupId>com.google.guava</groupId>
<artifactId>guava</artifactId> <artifactId>guava</artifactId>
...@@ -181,7 +180,7 @@ ...@@ -181,7 +180,7 @@
<dependency> <dependency>
<groupId>org.apache.poi</groupId> <groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId> <artifactId>poi-ooxml-schemas</artifactId>
<version>3.9</version> <version>3.17</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all --> <!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency> <dependency>
......
package org.nafmii.common.excle;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import java.lang.reflect.*;
/**
* 反射工具类.
* 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数.
*
* @author calvin
* @version 2013-01-15
*/
@SuppressWarnings("rawtypes")
public class Reflections {
private static final String SETTER_PREFIX = "set";
private static final String GETTER_PREFIX = "get";
private static final String CGLIB_CLASS_SEPARATOR = "$$";
private static Logger logger = LoggerFactory.getLogger(Reflections.class);
/**
* 调用Getter方法.
* 支持多级,如:对象名.对象名.方法
*/
public static Object invokeGetter(Object obj, String propertyName) {
Object object = obj;
for (String name : StringUtils.split(propertyName, ".")) {
String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name);
object = invokeMethod(object, getterMethodName, new Class[]{}, new Object[]{});
}
return object;
}
/**
* 调用Setter方法, 仅匹配方法名。
* 支持多级,如:对象名.对象名.方法
*/
public static void invokeSetter(Object obj, String propertyName, Object value) {
Object object = obj;
String[] names = StringUtils.split(propertyName, ".");
for (int i = 0; i < names.length; i++) {
if (i < names.length - 1) {
String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]);
object = invokeMethod(object, getterMethodName, new Class[]{}, new Object[]{});
} else {
String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]);
invokeMethodByName(object, setterMethodName, new Object[]{value});
}
}
}
/**
* 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数.
*/
public static Object getFieldValue(final Object obj, final String fieldName) {
Field field = getAccessibleField(obj, fieldName);
if (field == null) {
throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]");
}
Object result = null;
try {
result = field.get(obj);
} catch (IllegalAccessException e) {
logger.error("不可能抛出的异常{}", e.getMessage());
}
return result;
}
/**
* 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数.
*/
public static void setFieldValue(final Object obj, final String fieldName, final Object value) {
Field field = getAccessibleField(obj, fieldName);
if (field == null) {
throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]");
}
try {
field.set(obj, value);
} catch (IllegalAccessException e) {
logger.error("不可能抛出的异常:{}", e.getMessage());
}
}
/**
* 直接调用对象方法, 无视private/protected修饰符.
* 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用.
* 同时匹配方法名+参数类型,
*/
public static Object invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes,
final Object[] args) {
Method method = getAccessibleMethod(obj, methodName, parameterTypes);
if (method == null) {
throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");
}
try {
return method.invoke(obj, args);
} catch (Exception e) {
throw convertReflectionExceptionToUnchecked(e);
}
}
/**
* 直接调用对象方法, 无视private/protected修饰符,
* 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用.
* 只匹配函数名,如果有多个同名函数调用第一个。
*/
public static Object invokeMethodByName(final Object obj, final String methodName, final Object[] args) {
Method method = getAccessibleMethodByName(obj, methodName);
if (method == null) {
throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");
}
try {
return method.invoke(obj, args);
} catch (Exception e) {
throw convertReflectionExceptionToUnchecked(e);
}
}
/**
* 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问.
* <p>
* 如向上转型到Object仍无法找到, 返回null.
*/
public static Field getAccessibleField(final Object obj, final String fieldName) {
Validate.notNull(obj, "object can't be null");
Validate.notBlank(fieldName, "fieldName can't be blank");
for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
try {
Field field = superClass.getDeclaredField(fieldName);
makeAccessible(field);
return field;
} catch (NoSuchFieldException e) {//NOSONAR
// Field不在当前类定义,继续向上转型
continue;// new add
}
}
return null;
}
/**
* 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
* 如向上转型到Object仍无法找到, 返回null.
* 匹配函数名+参数类型。
* <p>
* 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
*/
public static Method getAccessibleMethod(final Object obj, final String methodName,
final Class<?>... parameterTypes) {
Validate.notNull(obj, "object can't be null");
Validate.notBlank(methodName, "methodName can't be blank");
for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {
try {
Method method = searchType.getDeclaredMethod(methodName, parameterTypes);
makeAccessible(method);
return method;
} catch (NoSuchMethodException e) {
// Method不在当前类定义,继续向上转型
continue;// new add
}
}
return null;
}
/**
* 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
* 如向上转型到Object仍无法找到, 返回null.
* 只匹配函数名。
* <p>
* 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
*/
public static Method getAccessibleMethodByName(final Object obj, final String methodName) {
Validate.notNull(obj, "object can't be null");
Validate.notBlank(methodName, "methodName can't be blank");
for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {
Method[] methods = searchType.getDeclaredMethods();
for (Method method : methods) {
if (method.getName().equals(methodName)) {
makeAccessible(method);
return method;
}
}
}
return null;
}
/**
* 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
*/
public static void makeAccessible(Method method) {
if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
&& !method.isAccessible()) {
method.setAccessible(true);
}
}
/**
* 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
*/
public static void makeAccessible(Field field) {
if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) || Modifier
.isFinal(field.getModifiers())) && !field.isAccessible()) {
field.setAccessible(true);
}
}
/**
* 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处
* 如无法找到, 返回Object.class.
* eg.
* public UserDao extends HibernateDao<User>
*
* @param clazz The class to introspect
* @return the first generic declaration, or Object.class if cannot be determined
*/
@SuppressWarnings("unchecked")
public static <T> Class<T> getClassGenricType(final Class clazz) {
return getClassGenricType(clazz, 0);
}
/**
* 通过反射, 获得Class定义中声明的父类的泛型参数的类型.
* 如无法找到, 返回Object.class.
* <p>
* 如public UserDao extends HibernateDao<User,Long>
*
* @param clazz clazz The class to introspect
* @param index the Index of the generic ddeclaration,start from 0.
* @return the index generic declaration, or Object.class if cannot be determined
*/
public static Class getClassGenricType(final Class clazz, final int index) {
Type genType = clazz.getGenericSuperclass();
if (!(genType instanceof ParameterizedType)) {
logger.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType");
return Object.class;
}
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
if (index >= params.length || index < 0) {
logger.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
+ params.length);
return Object.class;
}
if (!(params[index] instanceof Class)) {
logger.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
return Object.class;
}
return (Class) params[index];
}
public static Class<?> getUserClass(Object instance) {
Assert.notNull(instance, "Instance must not be null");
Class clazz = instance.getClass();
if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) {
Class<?> superClass = clazz.getSuperclass();
if (superClass != null && !Object.class.equals(superClass)) {
return superClass;
}
}
return clazz;
}
/**
* 将反射时的checked exception转换为unchecked exception.
*/
public static RuntimeException convertReflectionExceptionToUnchecked(Exception e) {
if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException
|| e instanceof NoSuchMethodException) {
return new IllegalArgumentException(e);
} else if (e instanceof InvocationTargetException) {
return new RuntimeException(((InvocationTargetException) e).getTargetException());
} else if (e instanceof RuntimeException) {
return (RuntimeException) e;
}
return new RuntimeException("Unexpected Checked Exception.", e);
}
}
package org.nafmii.common.excle.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Excel注解定义
* Created by tianc on 17/8/25.
*/
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelField {
/**
* 导出字段名(默认调用当前字段的“get”方法,如指定导出字段为对象,请填写“对象名.对象属性”,例:“area.name”、“office.name”)
*/
String value() default "";
/**
* 导出字段标题(需要添加批注请用“**”分隔,标题**批注,仅对导出模板有效)
*/
String title();
/**
* 字段类型(0:导出导入;1:仅导出;2:仅导入)
*/
int type() default 0;
/**
* 导出字段对齐方式(0:自动;1:靠左;2:居中;3:靠右)
*/
int align() default 0;
/**
* 导出字段字段排序(升序)
*/
int sort() default 0;
/**
* 如果是字典类型,请设置字典的type值
*/
String dictType() default "";
/**
* 反射类型
*/
Class<?> fieldType() default Class.class;
/**
* 字段归属组(根据分组导出导入)
*/
int[] groups() default {};
}
package org.nafmii.common.excle;
/**
* @author:zhoujh
* @Function:TODO
* @date 2021/4/29 15:35
* @ClassName:
* @version:
* @remark:
*/
public class test {
}
package org.nafmii.common.utils;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.nafmii.common.excle.Reflections;
import org.nafmii.common.excle.annotation.ExcelField;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
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.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
/**
* 导入Excel文件(支持“XLS”和“XLS”格式)
* Created by tianc on 17/8/25.
*/
public class ImportExcelUtils {
private static Logger log = LoggerFactory.getLogger(ImportExcelUtils.class);
/**
* 工作薄对象
*/
private Workbook wb;
/**
* 工作表对象
*/
private Sheet sheet;
/**
* 标题行号
*/
private int headerNum;
/**
* 构造函数
*
* @param fileName 导入文件,读取第一个工作表
* @param headerNum 标题行号,数据行号=标题行号+1
* @throws InvalidFormatException
* @throws IOException
*/
public ImportExcelUtils(String fileName, int headerNum)
throws InvalidFormatException, IOException {
this(new File(fileName), headerNum);
}
/**
* 构造函数
*
* @param file 导入文件对象,读取第一个工作表
* @param headerNum 标题行号,数据行号=标题行号+1
* @throws InvalidFormatException
* @throws IOException
*/
public ImportExcelUtils(File file, int headerNum)
throws InvalidFormatException, IOException {
this(file, headerNum, 0);
}
/**
* 构造函数
*
* @param fileName 导入文件
* @param headerNum 标题行号,数据行号=标题行号+1
* @param sheetIndex 工作表编号
* @throws InvalidFormatException
* @throws IOException
*/
public ImportExcelUtils(String fileName, int headerNum, int sheetIndex)
throws InvalidFormatException, IOException {
this(new File(fileName), headerNum, sheetIndex);
}
/**
* 构造函数
*
* @param file 导入文件对象
* @param headerNum 标题行号,数据行号=标题行号+1
* @param sheetIndex 工作表编号
* @throws InvalidFormatException
* @throws IOException
*/
public ImportExcelUtils(File file, int headerNum, int sheetIndex)
throws InvalidFormatException, IOException {
this(file.getName(), new FileInputStream(file), headerNum, sheetIndex);
}
/**
* 构造函数
*
* @param multipartFile 导入文件对象
* @param headerNum 标题行号,数据行号=标题行号+1
* @param sheetIndex 工作表编号
* @throws InvalidFormatException
* @throws IOException
*/
public ImportExcelUtils(MultipartFile multipartFile, int headerNum, int sheetIndex)
throws InvalidFormatException, IOException {
this(multipartFile.getOriginalFilename(), multipartFile.getInputStream(), headerNum, sheetIndex);
}
/**
* 构造函数
*
* @param fileName 导入文件对象
* @param headerNum 标题行号,数据行号=标题行号+1
* @param sheetIndex 工作表编号
* @throws InvalidFormatException
* @throws IOException
*/
public ImportExcelUtils(String fileName, InputStream is, int headerNum, int sheetIndex)
throws InvalidFormatException, IOException {
try{
if (fileName == null || fileName == "") {
throw new RuntimeException("导入文档为空!");
} else if (fileName.toLowerCase().endsWith("xls")) {
this.wb = new HSSFWorkbook(is);
} else if (fileName.toLowerCase().endsWith("xlsx")) {
this.wb = new XSSFWorkbook(is);
} else {
throw new RuntimeException("文档格式不正确!");
}
if (this.wb.getNumberOfSheets() < sheetIndex) {
throw new RuntimeException("文档中没有工作表!");
}
this.sheet = this.wb.getSheetAt(sheetIndex);
this.headerNum = headerNum;
log.debug("Initialize success.");
}finally {
is.close();
}
}
/**
* 获取行对象
*
* @param rownum
* @return
*/
public Row getRow(int rownum) {
return this.sheet.getRow(rownum);
}
/**
* 获取数据行号
*
* @return
*/
public int getDataRowNum() {
return headerNum + 1;
}
/**
* 获取最后一个数据行号
*
* @return
*/
public int getLastDataRowNum() {
return this.sheet.getLastRowNum() + headerNum;
}
/**
* 获取最后一个列号
*
* @return
*/
public int getLastCellNum() {
return this.getRow(headerNum).getLastCellNum();
}
/**
* 获取单元格值
*
* @param row 获取的行
* @param column 获取单元格列号
* @return 单元格值
*/
public Object getCellValue(Row row, int column) {
Object val = "";
try {
Cell cell = row.getCell(column);
if (cell != null) {
if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
val = cell.getNumericCellValue();
} else if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
val = cell.getStringCellValue();
} else if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) {
val = cell.getCellFormula();
} else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
val = cell.getBooleanCellValue();
} else if (cell.getCellType() == Cell.CELL_TYPE_ERROR) {
val = cell.getErrorCellValue();
}
}
} catch (Exception e) {
return val;
}
return val;
}
/**
* 获取导入数据列表
*
* @param cls 导入对象类型
* @param groups 导入分组
*/
public <E> List<E> getDataList(Class<E> cls, int... groups) throws InstantiationException, IllegalAccessException {
List<Object[]> annotationList = Lists.newArrayList();
// Get annotation field
Field[] fs = cls.getDeclaredFields();
for (Field f : fs) {
ExcelField ef = f.getAnnotation(ExcelField.class);
if (ef != null && (ef.type() == 0 || ef.type() == 2)) {
if (groups != null && groups.length > 0) {
boolean inGroup = false;
for (int g : groups) {
if (inGroup) {
break;
}
for (int efg : ef.groups()) {
if (g == efg) {
inGroup = true;
annotationList.add(new Object[]{ef, f});
break;
}
}
}
} else {
annotationList.add(new Object[]{ef, f});
}
}
}
// Get annotation method
Method[] ms = cls.getDeclaredMethods();
for (Method m : ms) {
ExcelField ef = m.getAnnotation(ExcelField.class);
if (ef != null && (ef.type() == 0 || ef.type() == 2)) {
if (groups != null && groups.length > 0) {
boolean inGroup = false;
for (int g : groups) {
if (inGroup) {
break;
}
for (int efg : ef.groups()) {
if (g == efg) {
inGroup = true;
annotationList.add(new Object[]{ef, m});
break;
}
}
}
} else {
annotationList.add(new Object[]{ef, m});
}
}
}
// Field sorting
Collections.sort(annotationList, new Comparator<Object[]>() {
public int compare(Object[] o1, Object[] o2) {
return new Integer(((ExcelField) o1[0]).sort()).compareTo(
new Integer(((ExcelField) o2[0]).sort()));
}
});
//log.debug("Import column count:"+annotationList.size());
// Get excel data
List<E> dataList = Lists.newArrayList();
for (int i = this.getDataRowNum(); i < this.getLastDataRowNum(); i++) {
E e = cls.newInstance();
int column = 0;
Row row = this.getRow(i);
StringBuilder sb = new StringBuilder();
for (Object[] os : annotationList) {
Object val = this.getCellValue(row, column++);
if (val != null) {
ExcelField ef = (ExcelField) os[0];
// If is dict type, get dict value
// if (StringUtils.isNotBlank(ef.dictType())) {
// val = DictUtils.getDictValue(val.toString(), ef.dictType(), "");
// }
// Get param type and type cast
Class<?> valType = Class.class;
if (os[1] instanceof Field) {
valType = ((Field) os[1]).getType();
} else if (os[1] instanceof Method) {
Method method = ((Method) os[1]);
if ("get".equals(method.getName().substring(0, 3))) {
valType = method.getReturnType();
} else if ("set".equals(method.getName().substring(0, 3))) {
valType = ((Method) os[1]).getParameterTypes()[0];
}
}
//log.debug("Import value type: ["+i+","+column+"] " + valType);
try {
if (valType == String.class) {
String s = String.valueOf(val.toString());
if (s.endsWith(".0")) {
val = StringUtils.substringBefore(s, ".0");
} else {
val = String.valueOf(val.toString());
}
} else if (valType == Integer.class) {
val = Double.valueOf(val.toString()).intValue();
} else if (valType == Long.class) {
val = Double.valueOf(val.toString()).longValue();
} else if (valType == Double.class) {
val = Double.valueOf(val.toString());
} else if (valType == Float.class) {
val = Float.valueOf(val.toString());
} else if (valType == Date.class) {
val = DateUtil.getJavaDate((Double) val);
} else {
if (ef.fieldType() != Class.class) {
val = ef.fieldType().getMethod("getValue", String.class).invoke(null, val.toString());
} else {
val = Class.forName(this.getClass().getName().replaceAll(this.getClass().getSimpleName(),
"fieldtype." + valType.getSimpleName() + "Type")).getMethod("getValue", String.class).invoke(null, val.toString());
}
}
} catch (Exception ex) {
log.info("Get cell value [" + i + "," + column + "] error: " + ex.toString());
val = null;
}
// set entity value
if (os[1] instanceof Field) {
Reflections.invokeSetter(e, ((Field) os[1]).getName(), val);
} else if (os[1] instanceof Method) {
String mthodName = ((Method) os[1]).getName();
if ("get".equals(mthodName.substring(0, 3))) {
mthodName = "set" + StringUtils.substringAfter(mthodName, "get");
}
Reflections.invokeMethod(e, mthodName, new Class[]{valType}, new Object[]{val});
}
}
sb.append(val + ", ");
}
dataList.add(e);
log.debug("Read success: [" + i + "] " + sb.toString());
}
return dataList;
}
/**
* 导入测试
*/
public static void main(String[] args) throws Throwable {
// File file = new File("D:\\excle");
// if (!file.exists()){
// file.getParentFile().mkdir();
// }
ImportExcelUtils ei = new ImportExcelUtils("D:\\excle/test1.xlsx", 1);
for (int i = ei.getDataRowNum(); i < ei.getLastDataRowNum(); i++) {
Row row = ei.getRow(i);
for (int j = 0; j < ei.getLastCellNum(); j++) {
Object val = ei.getCellValue(row, j);
System.out.print(val+", ");
}
System.out.print("\n");
}
}
}
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!