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. oracle-600错误

    event='10841 trace name context forever' 可以屏蔽这个ORA-00600错误. SQL> show parameter event NAME TYPE V ...

  2. hackerrank---Sets - Symmetric Difference

    题目链接 集合操作 附上代码: M = int(input()) m = set(map(int, raw_input().strip().split())) N = int(input()) n = ...

  3. Python学习之路7☞装饰器

    一:命名空间与作用域 1.1命名空间 局部命名空间: def foo(): x=1 def func(): pass 全局命名空间: import time class ClassName:pass ...

  4. 块级元素及内联元素对margin、padding的态度

    1.块级元素 margin:跟标准一样,设置该块级元素边框与同级兄弟元素或者父元素的距离,俗称外边距. padding:先延伸边框(也就是优先改变元素尺寸而不动元素中内容的位置),当边框碰到父元素的边 ...

  5. 【转载】GAWK AWK工具使用手册

    IBM GAWK入门资料http://www.ibm.com/developerworks/cn/education/aix/au-gawk/ AWK 是什么? 最简单地说,AWK 是一种用于处理文本 ...

  6. day10-02_多线程之进程与线程的pid

    一.多个线程之间PID的区别 主进程跟线程的pid是一样的 from threading import Thread from multiprocessing import Process impor ...

  7. keep-alive vue组件缓存避免多次加载相应的组件

    keep-alive vue组件缓存避免多次加载相应的组件

  8. tf.cast用法

    tf.cast:用于改变某个张量的数据类型 例如: import tensorflow as tf;import numpy as np; A = tf.convert_to_tensor(np.ar ...

  9. HDFS概念名称节点和数据节点-名称节点-文件系统元数据的持久状态

  10. laravel 5 自定义全局函数,怎么弄呢?

    在app/Helpers/(目录可以自己随便来) 下新建一个文件 functions.php 在functions.php 中加入这个方法 然后在 bootstrap/autoload.php 中添加 ...