package com.cinc.ecmp.utils;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List; import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.ss.usermodel.Cell;
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.ss.usermodel.WorkbookFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile; import com.cinc.ecmp.annotation.ExcelField;
import com.cinc.ecmp.enums.BackResultEnum;
import com.cinc.ecmp.exception.BasException; import lombok.extern.slf4j.Slf4j; /**
* @author j
* 操作方式:
* 根据Excel格式编写vo,vo编写方式参照com.cinc.ecmp.demo.vo.ExcelMaterialVo
*/
@Slf4j
public class ExcelParseUtils { public static <T> List<T> parse(MultipartFile file,Class<T> clazz){
Workbook hwb=null;
InputStream in = null;
try{
if(null == file){
throw new BasException(BackResultEnum.DATAPARSEERR);
}
in = file.getInputStream();
hwb=WorkbookFactory.create(in);
Sheet sheet=hwb.getSheetAt(0);
if(sheet==null) {
return null;
}
List<T> excelVoList=new ArrayList<T>();
Field[] fields=clazz.getDeclaredFields();
for(int i=sheet.getFirstRowNum()+1;i<sheet.getPhysicalNumberOfRows();i++) {
Row row = sheet.getRow(i);
if(null==row.getCell(1)||row.getCell(1).getCellType()==CellType.BLANK) {
break;//如果这一行的第一列为空,则终止解析
}
T object = clazz.newInstance();
for(Field field:fields) {
//获取该字段的列号
ExcelField excelField=field.getAnnotation(ExcelField.class);
if(null == excelField) {
continue;
}
int index = excelField.index();
String value="";
Cell cell = row.getCell(index);
if(null == cell) {
continue;
}
CellType cellType = cell.getCellType();
switch(cellType) {
case STRING:
value = String.valueOf(cell.getRichStringCellValue());
break;
case FORMULA:
try {
value = String.valueOf(cell.getNumericCellValue());
}catch (Exception e) {
value = String.valueOf(cell.getRichStringCellValue());
}
break;
case NUMERIC:
if(HSSFDateUtil.isCellDateFormatted(cell)) {
Date date=HSSFDateUtil.getJavaDate(cell.getNumericCellValue());
value=DateUtil.getDateTimeStringToDb(date);
}else {
DecimalFormat df = new DecimalFormat();
value = df.format(cell.getNumericCellValue());
}
break;
case BLANK:
break;
default:
throw new BasException(BackResultEnum.DATAPARSEERR);
}
//非空判断
if(excelField.required()&&StringUtils.isEmpty(value)) {
log.error("【{}不能为空】",excelField.desc());
throw new BasException(BackResultEnum.DATAPARSEERR);
}
//数据合法性判断
String[] dataScopes=excelField.inList();
if(!CollectionUtils.isEmpty(Arrays.asList(dataScopes))&&!Arrays.asList(dataScopes).contains(value)) {
log.error("【{}不合法】",excelField.desc());
throw new BasException(BackResultEnum.DATAPARSEERR);
}
//字段类型设置
Class<?> typeClass=field.getType();
Method method = clazz.getMethod("set" + Character.toUpperCase(field.getName().charAt(0)) + field.getName().substring(1), typeClass);
//将字段值设置到对象中
try {
if(typeClass==Integer.class) {
method.invoke(object, value.indexOf(".")>0?Integer.parseInt(value.substring(0, value.indexOf("."))):Integer.parseInt(value));
}else if(typeClass==BigDecimal.class) {
method.invoke(object, new BigDecimal(value.indexOf(",")>0?value.replaceAll(",", ""):value));
}else {
method.invoke(object, value.indexOf(",")>0?value.replaceAll(",", ""):value);
}
}catch (Exception e) {
log.error("【{}设置错误】",excelField.desc(),e);
throw new BasException(BackResultEnum.DATAPARSEERR);
}
}
if(excelVoList.contains(object)) {
log.error("【导入失败,数据存在重复】");
throw new BasException(BackResultEnum.DATAREPEATERR);
}
excelVoList.add(object);
}
return excelVoList;
}catch (Exception e) {
log.error("【文件上传失败】",e);
throw new BasException(BackResultEnum.FILEUPLOADERR);
}finally {
if(null != hwb){
try {
hwb.close();
} catch (IOException e) {
log.error("【文件流关闭失败】",e);
}
}
if(null != in){
try {
in.close();
} catch (IOException e) {
log.error("【文件流关闭失败】",e);
}
}
}
}
}

  vo实体类的编写:

package com.cinc.ecmp.demo.vo;

import java.math.BigDecimal;

import com.cinc.ecmp.annotation.ExcelField;

import lombok.Data;

/**
* @author
* @time 2019年7月2日 下午7:59:26
*/
@Data
public class ExcelMaterialVo { @ExcelField(index=0,required=true,desc="材料名称")
private String name; @ExcelField(index=1,required=true,desc="价格")
private BigDecimal price; @ExcelField(index=2,required=true,desc="采购数量")
private Integer count;
}

注解的编写:

package com.cinc.ecmp.annotation;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target; @Retention(RUNTIME)
@Target(FIELD)
@Inherited
public @interface ExcelField { /**
* Excel表格列顺序,起始为0
* @return
*/
int index(); /***
* 数据范围
* @return
*/
String[] inList() default {}; /***
* 正则
* @return
*/
String pattern() default ""; /***
* 字段描述
* @return
*/
String desc() default ""; /**
* 是否是必须的
*
* @return
*/
boolean required() default false;
}

  

@Override
public List<ExcelMaterialVo> upload(MultipartFile file){
List<ExcelMaterialVo> excelMaterialVoList=ExcelParseUtils.parse(file, ExcelMaterialVo.class);
return excelMaterialVoList;
}

excel转换成实体的更多相关文章

  1. Epplus下的一个将Excel转换成List的范型帮助类

    因为前一段时间公司做项目的时候,用到了Excel导入和导出,然后自己找了个插件Epplus进行操作,自己将当时的一些代码抽离出来写了一个帮助类. 因为帮助类是在Epplus基础之上写的,项目需要引用E ...

  2. C# 将DataTable数据源转换成实体类

    using System; using System.Collections.Generic; using System.Data; using System.Reflection; /// < ...

  3. 字符串js编码转换成实体html编码的方法(防范XSS攻击)

    js代码在html页面中转换成实体html编码的方法一: <!DOCTYPE html><html> <head>    <title>js代码转换成实 ...

  4. C# DataTable转换成实体列表 与 实体列表转换成DataTable

    /// <summary> /// DataTable转换成实体列表 /// </summary> /// <typeparam name="T"&g ...

  5. sql hibernate查询转换成实体或对应的VO Transformers

    sql查询转换成实体或对应的VO Transformers //addScalar("id") 默认查询出来的id是全部大写的(sql起别名也无效,所以使用.addScalar(& ...

  6. hibernate查询部分字段转换成实体bean

    //hibernate查询部分字段转换成实体bean /** * 查询线路信息 */ @Override public List<Line> getSimpleLineListByTj(M ...

  7. How to cast List<Object> to List<MyClass> Object集合转换成实体集合

    List<Object> list = getList(); return (List<Customer>) list; Compiler says: cannot cast  ...

  8. Table转换成实体、Table转换成实体集合(可转换成对象和值类型)

    /// <summary> /// Table转换成实体 /// </summary> /// <typeparam name="T">< ...

  9. DataTable转换成实体

    public static class DataTableToEntity { /// <summary> /// 将DataTable数据源转换成实体类 /// </summary ...

随机推荐

  1. poj3422 最小费用流

    一遍的话秩序要dp就好,但是这里要删去点.此题可以转化为最小费用流.开始我想了半天纠结怎么处理到过一次后值变0,看了书之后发现拆点解决了这个问题. 对于点t,拆为t-->t',容量为1,费用为负 ...

  2. Directx11教程(61) tessellation学习(3)

    原文:Directx11教程(61) tessellation学习(3)       现在我们看看在不同tess factor的情况下,三角形是如何细分的?(这儿三条边和内部tess factor值是 ...

  3. js简单倒计时

    不想每次用倒计时,都现写代码,比较烦,这里记一下,也顺便分享一些倒计时简单的逻辑. 如果你有更简单方便的代码,可以分享给大家. var method = { countdownObj: { timer ...

  4. Ubuntu 18.04中的Vim编辑器的高级配置

    VIM (Unix及类Unix系统文本编辑器) Vim是一个类似于Vi的著名的功能强大.高度可定制的文本编辑器,在Vi的基础上改进和增加了很多特性.VIM是开源软件. Vim普遍被推崇为类Vi编辑器中 ...

  5. hdu1503 LCS

    题意:如果有相同的字母,这些字母只输出一次.其余的都输出. 先做一次LCS,标记相同的字母,然后回溯输出. #include<stdio.h> #include<string.h&g ...

  6. mysql中时间字段datetime怎么判断为空和不为空

    mysql中时间字段datetime怎么判断为空和不为空一般为空都用null表示,所以一句sql语句就可以.select * from 表名 where 日期字段 is null;这里要注意null的 ...

  7. 【MySQL基础】Mysql获得当前日期的所在月的第一天

    Mysql获得当前日期的所在月的第一天 尊重劳动成果,请访问CSDN著者原文链接 http://blog.csdn.net/zixiao217/article/details/51908506 Ste ...

  8. epoll简介(一)

    一:概述   1:简介 EPOLL类似于POLL,是Linux特有的一种IO多路复用的机制.它在2.5.44内核中引入. 对于大量的描述符处理,EPOLL更有优势,它提供了三个系统调用来创建管理epo ...

  9. Strange Way to Express Integers

    I. Strange Way to Express Integers 题目描述 原题来自:POJ 2891 给定 2n2n2n 个正整数 a1,a2,⋯,ana_1,a_2,\cdots ,a_na​ ...

  10. js循环遍历数组(对象)

    1,for循环 对于循环应该是最常用的一种遍历方式了,通常用来遍历数组结构. let arr = [a,b,d];for (let i=0; i<arr.length; i++){ consol ...