excel导入功能

家电维修 2023-07-16 19:16www.caominkang.com家电维修技术

------这里只是测试类------实际使用的看下面

需要用到ExcelUtils工具类

ExcelUtils的主要作用是把Excel转化成 List>类型的数据,方便遍历

package tech.niua.mon.excelimport;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import .apache.poi.hssf.usermodel.HSSFWorkbook;
import .apache.poi.ss.usermodel.;
import .apache.poi.xssf.usermodel.XSSFWorkbook;


public class ExcelUtils {

 private final static String excel2003L =".xls"; //2003- 版本的excel
 private final static String excel2007U =".xlsx";   //2007+ 版本的excel

 
 public static List> getListByExcel(InputStream in, String fileName) thros Exception{
  List> list = null;

  //创建Excel工作薄
  Workbook ork = getWorkbook(in,fileName);
  if(null == ork){
   thro ne Exception("创建Excel工作薄为空!");
  }
  Sheet sheet = null;  //页数
  Ro ro = null;  //行数
  Cell cell = null;  //列数

  list = ne ArrayList>();
  //遍历Excel中所有的sheet
  for (int i = 0; i < ork.getNumberOfSheets(); i++) {
   sheet = ork.getSheetAt(i);
   if(sheet==null){continue;}

   //遍历当前sheet中的所有行
   for (int j = sheet.getFirstRoNum(); j <= sheet.getLastRoNum(); j++) {
    ro = sheet.getRo(j);
    if(ro==null){continue;}

    //遍历所有的列
    List li = ne ArrayList();
    for (int y = ro.getFirstCellNum(); y < ro.getLastCellNum(); y++) {
     cell = ro.getCell(y);
     li.add(getValue(cell));
    }
    list.add(li);
   }
  }

  return list;

 }

 
 public static  Workbook getWorkbook(InputStream inStr,String fileName) thros Exception{
  Workbook b = null;
  String fileType = fileName.substring(fileName.lastIndexOf("."));
  if(excel2003L.equals(fileType)){
   b = ne HSSFWorkbook(inStr);  //2003-
  }else if(excel2007U.equals(fileType)){
   b = ne XSSFWorkbook(inStr);  //2007+
  }else{
   thro ne Exception("解析的文件格式有误!");
  }
  return b;
 }

 
 //解决excel类型问题,获得数值
 public static String getValue(Cell cell) {
  String value = "";
  if(null==cell){
   return value;
  }
  sitch (cell.getCellType()) {
   //数值型
   case NUMERIC:
    if (DateUtil.isCellDateFormatted(cell)) {
     //如果是date类型则 ,获取该cell的date值
     Date date = DateUtil.getJavaDate(cell.getNumericCellValue());
     SimpleDateFormat format = ne SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
     value = format.format(date);;
    }else {// 纯数字
     BigDecimal big=ne BigDecimal(cell.getNumericCellValue());
     value = big.toString();
     //解决1234.0  去掉后面的.0
     if(null!=value&&!"".equals(value.trim())){
      String[] item = value.split("[.]");
      if(1 
 
package test.excel;

import .junit.Test;

import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Field;
import java.util.List;

public class TestExcel {

 @Test
 public void importExcel(){

  String filepath = "/Users/Desk/sys_user.xlsx";
  FileInputStream inputStream = null;
  try {
   inputStream = ne FileInputStream(ne File(filepath));
   //把Excel文件转化成 List>类型的数据
   List> list = ExcelUtils.getListByExcel(inputStream, filepath);
   System.out.println(list);
   //定义第一行
   List firstRos = null;
   //数据不为空
   if(list != null && list.size() > 0){
    //拿到第一行
    firstRos = list.get(0);
   }
   //遍历每一行
   for (int i = 1; i < list.size(); i++) {
    //拿到这一行
    List ros = list.get(i);
    //初始化对象
    Demo demo = ne Demo();
    //遍历这一行
    for (int j = 0; j < ros.size(); j++) {
     //定义cellVal,拿到每一个的值
     String cellVal = (String) ros.get(j);
     //把对象,标题名,值 都传过去
     TestExcel.setFieldValueByFieldName(demo, firstRos.get(j).toString().trim(), cellVal);
    }
    System.out.println(demo);
   }
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

// @Test
// public void testRef(){
//  tech.niua.admin.test.domain.Test test = ne tech.niua.admin.test.domain.Test();
//  test.setId(100L);
//  test.setName("angzhen");
//  Object id = TestExcel.getFieldValueByFieldName("id", test);
//  Object username = TestExcel.getFieldValueByFieldName("username", test);
//  System.out.println(username);
// }

 private static void setFieldValueByFieldName(Object object, String fieldName, Object val) {
  try {
   //反射拿到所有的object的属性值
   Field[] fields = object.getClass().getDeclaredFields();
   //遍历一遍
   for (int i = 0; i < fields.length; i++) {
    //定义一个Field类型的值,遍历给它赋值
    Field field = fields[i];
    //如果传过来的fieldName等于field数据中的名称名
    if(fieldName.equals(field.getName())){
     //把它set进去
     field.set(object, val.toString());
     return;
    }
   }
  } catch (Exception e) {
   e.printStackTrace();

  }
 }

 private static Object getFieldValueByFieldName(String fieldName, Object object) {
  try {
   Field field = object.getClass().getField(fieldName);
   //设置对象的访问权限,保证对private的属性的访问
   return  field.get(object);
  } catch (Exception e) {
//   e.printStackTrace();
   return null;
  }
 }
}
 
 

主要步骤

定义一个文件输入流,把excel文件放进输入流

调用ExcelUtils.getListByExcel(inputStream, filepath)  【这里把输入流和路径名当作参数,路径名当作参数是为了拿到文件名的后缀,判断xls还是xlsx,到ExcelUtils里判断版本】拿到excel文件转换成List>类型的数据

如果数据不为空的话,拿到数据中的第一行 list.get(0)  即标题名

for循环遍历每一行 list.get(i) ,在每一行初始化Demo对象(目的要给它赋值)

嵌套for循环遍历每一列ros.get(j),拿到每一个格的值

调用setFieldValueByFieldName方法,在一行内的每一次列遍历的时候都调用一次,而且把对应的标题名也当作参数传进去

每一行遍历结束,一个完整的Demo对象就被赋值成功了,就可以在业务中把它添加进数据库了

setFieldValueByFieldName方法

把对象,标题名,数值 传过去

通过反射拿到对象的属性值,遍历对象的属性值,如果属性名等于传过来的标题名,就可以对齐进行set,把数值set进对象里,做到了赋值 

package test.excel;

import tech.niua.mon.annotation.Excel;


public class Demo {
 public String id;
 @Excel(name = "姓名")
 public String name;
 public String createTime;

 public String getId() {
  return id;
 }

 public void setId(String id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getCreateTime() {
  return createTime;
 }

 public void setCreateTime(String createTime) {
  this.createTime = createTime;
 }

 @Override
 public String toString() {
  return "Demo{" +
    "id='" + id + ''' +
    ", name='" + name + ''' +
    ", createTime='" + createTime + ''' +
    '}';
 }
}

 如果在实体类中添加注解

 


下面是可以实际应用的方法!!!!!!!

--改进--

因为通过上传获取服务器文件路径信息,把服务器文件路径返回到前端,再通过传递路径信息到后端对文件路径的文件进行操作

有两个缺点

1.两次请求,慢

2.客户端可以知道服务器的路径,不安全

点击上传之间上传成功

后端接收到文件,把文件转成输入流传到getObjectList方法中,需要传入的还有实体类(因为需要反射获取实体类类型,在方法中给实体类List赋值),返回过来的List转换成实体类List,然后再通过mybatisplus插入进数据库

Controller层

  
 @PostMapping("/imports")
 @PreAuthorize("hasAuthority('/signature/imports')")
 //传进来二进制文件数据
 public ResultJson uploadFile(MultipartFile file) thros Exception {
   Signature signature =ne Signature();
   List objects = ObjectList.getObjectList(file,signature);
   List list =  (List) (List)objects;
   boolean flag = signatureService.saveOrUpdateBatch(list);
   if(flag){
    return ResultJson.ok();
   }
   return ResultJson.failure(ResultCode.NOT_UPDATE);

 } 
  
 

封装的文件转List方法

package tech.niua.mon.excelimport;

import .springframeork.eb.multipart.MultipartFile;
import tech.niua.mon.annotation.Excel;
import tech.niua.mon.config.NiuaConfig;
import tech.niua.mon.utils.file.FileUploadUtils;

import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;


public class ObjectList {
 
 public static List getObjectList(MultipartFile file, Object object) thros Exception {
  //通过反射拿到对象
  Class cls = object.getClass();
  // 上传文件路径C:/Users/10565/Desk/niuniu/upload
  String filePath = NiuaConfig.getUploadPath();
  // 上传并返回新文件名称 2022/04/28/3015c5d0-8e05-4e02-b1f6-81440f373b56.xlsx
  String fileName = FileUploadUtils.upload(filePath, file);
  //完整的上传文件的路径
  fileName =filePath+ File.separator+fileName;
  //把上传的文件转换成输入流
  FileInputStream fileInputStream = ne FileInputStream(ne File(fileName));
  //输入流 和 文件路径  作为参数传入 获取List>类型数据的方法中
  List> list = ExcelUtils.getListByExcel(fileInputStream,fileName);
  
  //初始化标题
  List firstRos = null;
  //如果转换过来的数据不为空,拿到标题
  if (list != null && list.size() > 0) {
   firstRos = list.get(0);
  }
  //初始化实际数据
  List excelDate = ne ArrayList<>();
  //从一开始遍历,为的是拿到数据
  for (int i = 1; i < list.size(); i++) {
   //每一行实例化一个List数据,后面插入的也是这些
   List ros = list.get(i);
   //实例化对象,方便赋值
   Object obj = cls.neInstance();
   //对obj的每一个的字段进行赋值
   for (int j = 0; j < ros.size(); j++) {
    //把excel转过来的数据的每个字段的值转换成String类型
    String cellVal = (String) ros.get(j);
    //对obj进行赋值(实体类,字段名,字段值)
    ObjectList.setFieldValueByFieldName(obj, firstRos.get(j).toString().trim(), cellVal);
   }
   //添加进List,每个obj都是一条数据
   excelDate.add(obj);
  }
  return excelDate;
 }
 //调用一次这个方法只能给一条数据的一个字段赋值
 public static void setFieldValueByFieldName(Object object, String fieldName, Object val) {
  try {
   //反射拿到实体类每个变量的数据
   Field[] fields = object.getClass().getDeclaredFields();
   //把实体类每个变量遍历一遍
   for (int i = 0; i < fields.length; i++) {
    //一个实体类的一个变量,代表一种类型
    Field field = fields[i];
    //拿到当前实体类字段的Excel注解
    Excel excel = field.getAnnotation(Excel.class);
    if(excel==null){
     continue;
    }
    //如果excel转化过来的字段值和便利店实体类的遍历的注解名相同,说明对应上了,赋值!!
    if(fieldName.equals(excel.name())||fieldName.equals(field.getName())){
     //把属性值set进对象
     
     if(field.getType()==Integer.class){
      //把有这个类型的要被赋值的对象和这个类型的数值当作参数,可以赋值
      field.set(object,Integer.valueOf(val.toString()));
     } else if(field.getType()==Long.class){
      field.set(object,Long.valueOf(val.toString()));
     }
     else if(field.getType()== LocalDateTime.class){
      DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
      LocalDateTime time = LocalDateTime.parse(val.toString(),df);
      field.set(object,time);
     }
     else
      field.set(object, val);
     return;
    }

   }
  } catch (Exception e) {
   e.printStackTrace();

  }
 }

}
 
 
package tech.niua.mon.excelimport;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import .apache.poi.hssf.usermodel.HSSFWorkbook;
import .apache.poi.ss.usermodel.;
import .apache.poi.xssf.usermodel.XSSFWorkbook;


public class ExcelUtils {

 private final static String excel2003L =".xls"; //2003- 版本的excel
 private final static String excel2007U =".xlsx";   //2007+ 版本的excel

 
 public static List> getListByExcel(InputStream in, String fileName) thros Exception{
  List> list = null;

  //创建Excel工作薄
  Workbook ork = getWorkbook(in,fileName);
  if(null == ork){
   thro ne Exception("创建Excel工作薄为空!");
  }
  Sheet sheet = null;  //页数
  Ro ro = null;  //行数
  Cell cell = null;  //列数

  list = ne ArrayList>();
  //遍历Excel中所有的sheet
  for (int i = 0; i < ork.getNumberOfSheets(); i++) {
   sheet = ork.getSheetAt(i);
   if(sheet==null){continue;}

   //遍历当前sheet中的所有行
   for (int j = sheet.getFirstRoNum(); j <= sheet.getLastRoNum(); j++) {
    ro = sheet.getRo(j);
    if(ro==null){continue;}

    //遍历所有的列
    List li = ne ArrayList();
    for (int y = ro.getFirstCellNum(); y < ro.getLastCellNum(); y++) {
     cell = ro.getCell(y);
     li.add(getValue(cell));
    }
    list.add(li);
   }
  }

  return list;

 }

 
 public static  Workbook getWorkbook(InputStream inStr,String fileName) thros Exception{
  Workbook b = null;
  String fileType = fileName.substring(fileName.lastIndexOf("."));
  if(excel2003L.equals(fileType)){
   b = ne HSSFWorkbook(inStr);  //2003-
  }else if(excel2007U.equals(fileType)){
   b = ne XSSFWorkbook(inStr);  //2007+
  }else{
   thro ne Exception("解析的文件格式有误!");
  }
  return b;
 }

 
 //解决excel类型问题,获得数值
 public static String getValue(Cell cell) {
  String value = "";
  if(null==cell){
   return value;
  }
  sitch (cell.getCellType()) {
   //数值型
   case NUMERIC:
    if (DateUtil.isCellDateFormatted(cell)) {
     //如果是date类型则 ,获取该cell的date值
     Date date = DateUtil.getJavaDate(cell.getNumericCellValue());
     SimpleDateFormat format = ne SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
     value = format.format(date);;
    }else {// 纯数字
     BigDecimal big=ne BigDecimal(cell.getNumericCellValue());
     value = big.toString();
     //解决1234.0  去掉后面的.0
     if(null!=value&&!"".equals(value.trim())){
      String[] item = value.split("[.]");
      if(1 
 

通用Path实体类

package tech.niua.mon.domain;

import lombok.Data;

@Data
public class Path {
 private String url;
 private String fileName;
 private String path;
}

前端直接把文件传到后端 

Copyright © 2016-2025 www.jianfeikang.com 建飞家电维修 版权所有 Power by