Java结合POI框架实现Excel导入

news2024/10/5 20:26:08

Java结合POI框架实现Excel导入

  • 一、流程概念
  • 二、conroller中的方法
  • 三、导入成功

一、流程概念

我们需要把excel通过上传得方式导入数据库,需要以下几个步骤

  • 将excel上传到服务器指定文件夹内并重命名(upload)
  • 获取到文件公共路径和别名路径
  • 将上传得文件转化成输入流(poi框架)
  • 通过方法,将输入流文件数值转化成List<List>对象
  • 遍历excel中得值,调用一次setFieldValueByFieldName方法,就对属性赋值一次,每次循环拿到一条数据,最终得到整个数据。
  • 后台调用getObjectList(file, Exam.class)。
    在这里插入图片描述

二、conroller中的方法

@PostMapping("/upload")

public ResultJson uploadFile(MultipartFile file ) throws Exception {
    List<Object> objects = ObjectList.getObjectList(file,  Exam.class);
    List<Exam> list = (List) objects;
    boolean flag = examService.saveOrUpdateBatch(list);
    if (flag) {
        return ResultJson.ok();
    }
    return ResultJson.failure(ResultCode.NOT_UPDATE);
}

前天传过来得是二进制文件MultipartFile file
调用getObjectList方法(二进制文件,实体类对象)

package tech.niua.common.excelimport;
 
public class ObjectList {
    /**
     * 封装的将Excel文件信息转换成List<Object>的方法,需要传实体类
     * @param file
     * @param
     * @return
     * @throws Exception
     */
    public static List<Object> getObjectList(MultipartFile file, Class cls) throws Exception {
        //获取到了文件根路径
        String filePath = NiuaConfig.getUploadPath();
        // 上传并返回文件除根路径得路径 052d1c92-fc6a-4e15-a7c9-7d193c1a4bec.xlsx
        String fileName = FileUploadUtils.upload(filePath, file);
        //完整的上传文件的路径
        fileName =filePath+ File.separator+fileName;
        //把上传的文件转换成输入流(因为我们使用得是poi框架,要求使用输入流)
        FileInputStream fileInputStream = new FileInputStream(new File(fileName));
        //输入流 和 文件路径  作为参数传入 获取List<List<Object>>类型数据的方法中
        List<List<Object>> list = ExcelUtils.getListByExcel(fileInputStream,fileName);
 
        /**
         * 将数据转换成List<Object>类型的数据
         */
        //初始化标题
        List<Object> firstRows = null;
        //如果转换过来的数据不为空,拿到标题,在之前的方法中判断过是否为空
        if (list != null && list.size() > 0) {
            firstRows = list.get(0);
        }
        //初始化实际数据 初始化对象
        List<Object> excelDate = new ArrayList<>();
        //从一开始遍历,为的是拿到数据
        for (int i = 1; i < list.size(); i++) {
            //每一行实例化一个List<Object>数据,后面插入的也是这些
            List<Object> rows = list.get(i);
            //实例化对象,方便赋值(for里面是每次都改变数据,防止都访问这一个地址)
            Object obj = cls.newInstance();
            //对obj的每一个的字段进行赋值
            for (int j = 0; j < rows.size(); j++) {
                //把excel转过来的数据的每个字段的值转换成String类型
                String cellVal = (String) rows.get(j);
                //对obj进行赋值(对象,字段名,字段值)
                ObjectList.setFieldValueByFieldName(obj, firstRows.get(j).toString().trim(), cellVal);
            }
            //添加进List<Object>,每个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];
                ///可以访问私有
                field.setAccessible(true);
                //判断excel注解修饰
                Excel excel = field.getAnnotation(Excel.class);
                if(excel== null){
                    continue;
                }
                //如果excel转化过来的标题名和实体类字段或者实体类注解相同,说明对应上了,赋值!!
                if(fieldName.equals(excel.name())||fieldName.equals(field.getName())){
                    //将excel中得String类型得数值,转化成对应实体类属性,把属性值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);
                    }
 
                }
 
            }
        } catch (Exception e) {
            e.printStackTrace();
 
        }
    }
 
}
package tech.niua.common.excelimport;
 
 
 
/**
 * Created by ws
 * Date :2022/4/29
 * Description : excel导入工具类
 * Version :1.0
 */
public class ExcelUtils {
 
    private final static String excel2003L =".xls";    //2003- 版本的excel
    private final static String excel2007U =".xlsx";   //2007+ 版本的excel
 
    /**
     * @Description:获取IO流中的数据,组装成List<List<Object>>对象
     * @param in,fileName
     * @return
     * @throws IOException
     */
    public static List<List<Object>> getListByExcel(InputStream in, String fileName) throws Exception{
        List<List<Object>> list = null;
 
        //创建Excel工作薄
        Workbook work = getWorkbook(in,fileName);
        if(null == work){
            throw new Exception("创建Excel工作薄为空!");
        }
        Sheet sheet = null;  //页数
        Row row = null;  //行数
        Cell cell = null;  //列数
 
        list = new ArrayList<List<Object>>();
        //遍历Excel中所有的sheet
        for (int i = 0; i < work.getNumberOfSheets(); i++) {
            //取某个sheet
            sheet = work.getSheetAt(i);
            if(sheet== null){continue;}
 
            //遍历当前sheet中的所有行
            for (int j = sheet.getFirstRowNum(); j <= sheet.getLastRowNum(); j++) {
                row = sheet.getRow(j);
                if(row == null){continue;}
 
                //遍历所有的列
                List<Object> li = new ArrayList<Object>();
                for (int y = row.getFirstCellNum(); y < row.getLastCellNum(); y++) {
                    cell = row.getCell(y);
                    li.add(getValue(cell));
                }
                list.add(li);
            }
        }
 
        return list;
 
    }
 
    /**
     * @Description:根据文件后缀,自适应上传文件的版本
     * @param inStr,fileName
     * @return
     * @throws Exception
     */
    public static Workbook getWorkbook(InputStream inStr, String fileName) throws Exception{
        Workbook wb = null;
        String fileType = fileName.substring(fileName.lastIndexOf("."));
        if(excel2003L.equals(fileType)){
            wb = new HSSFWorkbook(inStr);  //2003-
        }else if(excel2007U.equals(fileType)){
            wb = new XSSFWorkbook(inStr);  //2007+
        }else{
            throw new Exception("解析的文件格式有误!");
        }
        return wb;
    }
 
    /**
     * @Description:对表格中数值进行格式化
     * @param cell
     * @return
     */
    //解决excel类型问题,获得数值
    public static String getValue(Cell cell) {
        String value = "";
        if(null == cell){
            return value;
        }
        switch (cell.getCellType()) {
            //数值型
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    //如果是date类型则 ,获取该cell的date值
                    Date date = DateUtil.getJavaDate(cell.getNumericCellValue());
                    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    value = format.format(date);;
                }else {// 纯数字
                    BigDecimal big= new BigDecimal(cell.getNumericCellValue());
                    value = big.toString();
                    //解决1234.0  去掉后面的.0
                    if(null!= value&&!"".equals(value.trim())){
                        String[] item = value.split("[.]");
                        if(1<item.length&&"0".equals(item[1])){
                            value = item[0];
                        }
                    }
                }
                break;
            //字符串类型
            case STRING:
                value = cell.getStringCellValue();
                break;
            // 公式类型
            case FORMULA:
                //读公式计算值
                value = String.valueOf(cell.getNumericCellValue());
                if (value.equals("NaN")) {// 如果获取的数据值为非法值,则转换为获取字符串
                    value = cell.getStringCellValue();
                }
                break;
            // 布尔类型
            case BOOLEAN:
                value = " "+ cell.getBooleanCellValue();
                break;
            default:
                value = cell.getStringCellValue();
        }
        if("null".endsWith(value.trim())){
            value= "";
        }
        return value;
    }
 
}

三、导入成功

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/516111.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

InsCode再进步,AI 辅助编程帮你打开思路

文章目录 一、前言二、使用 AI 辅助完成代码1. 基于模板创建项目2. 使用 AI 辅助开拓思路3. 使用 AI 辅助生成代码4. 使用 AI 辅助优化代码 三、InsCode AI Chat 的使用建议四、总结 一、前言 你好&#xff0c;我是小雨青年&#xff0c;一名独立开发的程序员。 在之前的文章中…

Ubuntu22.04安装PyTorch1.13.0 GPU版本

目录 一、电脑相关信息 1. 电脑显卡环境&#xff1a; 二、安装Pytorch1.13.0/cu117&#xff08;GPU版本&#xff09; 1. 准备&#xff1a;新建虚拟环境 2. 用conda在线安装pytorch1.13.0/cu117&#xff08;pytorch1.13.0 torchvision0.14.0 pytorch-cuda11.7&#xff09;…

博客管理系统前端分析

目录结构博客列表页&#xff1a;所有页面共同的样式代码&#xff1a;博客详情页博客登录页博客编辑页 目录结构 博客列表页&#xff1a; 页面效果&#xff1a; 代码&#xff1a; <!-- 博客列表页 --> <!DOCTYPE html> <html lang"en"> <head…

计算机视觉的深度学习 Lecture4:Optimization 笔记 EECS 498.008

数值计算梯度 问题是慢&#xff0c;每个都要注意做步长&#xff0c;求除法。 应该用求导方法解决。 SGD通过每次抽取一部分&#xff08;mini-batch&#xff09;来计算梯度&#xff0c;而不是遍历整个数据集来求梯度&#xff0c;大大增大了求梯度速度&#xff0c;并且性能不…

TCP 协议特性详解

TCP 协议特性总结 TCP协议特点TCP协议段格式TCP原理确认应答&#xff08;安全机制&#xff09;超时重传&#xff08;安全机制&#xff09;连接管理&#xff08;安全机制&#xff09;(面试高频题)三次握手四次挥手 滑动窗口&#xff08;效率机制&#xff09;流量控制&#xff08…

【LeetCode】数据结构题解(8)[链表中的入口节点]

链表中的入口节点 1.题目来源2.题目描述3.解题思路4.代码展示 1.题目来源 链表中的入口节点 2.题目描述 给定一个链表&#xff0c;返回链表开始入环的第一个节点。 从链表的头节点开始沿着 next 指针进入环的第一个节点为环的入口节点。如果链表无环&#xff0c;则返回 null…

08-HTML-样式和语意标签

1、<style> 标签用于为 HTML 文档定义样式信息。type 属性是必需的&#xff0c;定义 style 元素的内容。唯一可能的值是 "text/css"。style 元素位于 head 部分中。 2、<div> 可定义文档中的分区或节&#xff08;division/section&#xff09;。<div&…

Unity Audio -- (4)为声音添加特殊效果

本节我们使用声音混响区域&#xff08;audio reverb zone&#xff09;实现一些特殊效果。 什么是混响区域&#xff08;audio reverb zone&#xff09; 不同障碍物对声波的反射和吸收能力不同&#xff0c;坚硬平整表面反射声波能力强&#xff0c;松软多孔的表面吸收声波能力强。…

yolov5环境搭建(Anaconda-py3.9、PyTorch-CPU、yolov5-4.0、PyCharm)

1.环境准备 Windows 10Anaconda&#xff08;基于Python3.9&#xff09;&#xff0c;已配置好环境变量yolov5相关的代码、权重文件等&#xff0c;已经打包整理好&#xff0c;可以通过百度网盘绿色下载。链接: https://pan.baidu.com/s/1okVkfpqjI5wD6PigK-AH0w?pwdyscw 提取码…

RabbitMQ发布/订阅(交换机)

目录 RabbitMQ发布/订阅(交换机)介绍Fanout&#xff08;广播&#xff09;声明队列和交换机publisher 消息发送consumer消息接收 Direct&#xff08;定向&#xff09;consumer消息接收,基于注解声明队列和交换机publisher 消息发送总结 Topic&#xff08;通配符&#xff09;publ…

【腾讯云Finops Crane集训营】利用云原生成本优化项目实现降本增效泰酷辣~

Crane 是一个基于 FinOps 的云资源分析与成本优化平台。在保证客户应用运行质量的前提下实现极致的降本。 文章目录 一、 前言&#x1f350;二、 Crane开源项目简介&#x1f34e;2.1. Crane整体框架&#x1f352;2.2. Crane主要功能&#x1f345; 三、Crane实验前期准备&#x…

Cesium入门之二:引用Cesium并创建第一个三维地球

这一节我们来引入Cesium并创建第一个三维地图程序 Cesium的引入 1、新建一个文件夹&#xff0c;命名为first_cesium,在该文件夹下新建一个Build文件夹&#xff0c;将上一节我们下载的Cesium文件夹下Build文件夹---->Cesium文件夹下的文件全部拷贝到first_cesium---->Bu…

关于阿里云的图像搜索的创建和使用

大家好哇&#xff0c;我又来了&#xff0c;这次我们来聊下关于阿里云的图像搜索功能的创建和使用。 https://free.aliyun.com/?crowdpersonal 1、我们可以通过上面的链接进入到阿里云云产品免费试用页面&#xff0c;这里主要是阿里云为新手用户提供的免费体验的权益&#xff…

Cesium入门之一:Cesium本地运行

Cesium简介 Cesium是一个开源的、面向三维地球和地图的JavaScript库&#xff0c;它是基于Apache2.0许可的开源程序&#xff0c;可以免费的用于商业用途&#xff1b; Cesium下载 Cesium的官网地址是&#xff1a;https://cesium.com/platform/cesiumjs/&#xff0c;由于Cesium…

ChatGPT 提示语——AI提示词玩家,提示词就是和AI沟通语言的桥梁!

前言&#xff1a; 众所周知&#xff0c;在AI的世界里&#xff0c;提示词就是和AI沟通语言的桥梁&#xff0c;提示关键词常用于AI对话及AI绘画等相关场景&#xff0c;通过准确的使用关键词&#xff0c;你就能更好的让AI辅助自己的工作&#xff0c;其中的成分重要性不言而喻&…

MySQL---基本操作DQL(上)(基本查询语法,算术运算符,比较运算符,逻辑运算符,位运算符)

1. 基本查询语法 select [all|distinct] <目标列的表达式1> [别名], <目标列的表达式2> [别名]... from <表名或视图名> [别名],<表名或视图名> [别名]... [where<条件表达式>] [group by <列名> [having <条件表达式>]] [o…

JAVA学习日记 (放假了,哈哈)

每日一题 1016. 子串能表示从 1 到 N 数字的二进制串 难度中等122收藏分享切换为英文接收动态反馈 给定一个二进制字符串 s 和一个正整数 n&#xff0c;如果对于 [1, n] 范围内的每个整数&#xff0c;其二进制表示都是 s 的 子字符串 &#xff0c;就返回 true&#xff0c;否…

时间轮的golang实践浅析

引言 下列代码模仿一段RPC请求的执行过程&#xff0c;执行后会有哪些问题&#xff1a; RPC代码示例答案&#xff1a;因为超时控制后未阻断后续请求&#xff0c;导致并发读写产生Panic思考&#xff1a;客户端发起 HTTP 请求后&#xff0c;如果在指定时间内没有收到服务器的响应…

软件开发安全

软件开发安全 软件安全开发生命周期软件生命周期模型软件生命周期模型-瀑布模型软件生命周期模型-迭代模型软件生命周期模型-增量模型软件生命周期模型-快速原型模型软件生命周期模型-螺旋模型软件生命周期模型-净室模型软件安全重要性–软件危机 软件安全问题产生-内因软件安全…

51单片机(十一)DS1302实时时钟

❤️ 专栏简介&#xff1a;本专栏记录了从零学习单片机的过程&#xff0c;其中包括51单片机和STM32单片机两部分&#xff1b;建议先学习51单片机&#xff0c;其是STM32等高级单片机的基础&#xff1b;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 &#xff1a;适用于想要…