应用 POI 解析 Excel 表格并批量上传到数据库

2023-10-31

  在日常生活中,我们时常会遇到添加用户之类的操作,但是这类操作,只能一位一位的添加。遇到向我这种强迫症晚期患者,会被烦死… 那么应用 POI 解析含有用户信息的 EXCEL 表格会省很多时间。本文针对解析 EXCEL 表格以及将表格上的内容批量上传到数据库提供一项实用的解决方案。
在这里插入图片描述



一、导入 pom 坐标

<!--解析excel-->
<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi-ooxml</artifactId>
  <version>3.9</version>
</dependency>
<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi</artifactId>
  <version>3.9</version>
</dependency>
<dependency>
  <groupId>joda-time</groupId>
  <artifactId>joda-time</artifactId>
  <version>2.10.1</version>
</dependency>

二、编写解析 Excel 表格的工具类

  创建 ParseExcelUtil 工具类,编写解析指定对象表格的静态方法。方法传入的参数分别是上传文件的路径,以及文件名称。


为解析 EXCEL 做准备工作:

  1. 获取解析文件的输入流。
  2. 根据文件类型(xls、xlsx)创建一个工作簿。(这样两种xls、xlsx后缀的表格都会被解析)
  3. 获取的第一个sheet。(可根据索引检索指定的sheet)
  4. 设置存储 list 集合。

对 EXCEL 进行解析流程如下:
在这里插入图片描述


import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
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.xssf.usermodel.XSSFWorkbook;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class ParseExcelUtil {

    private static InputStream in;
    private static Workbook workbook;
    private static Sheet sheet;

    public static List<Coach> parseCoachExcel(String path, String fileName) throws IOException, ParseException {
        //1.获取解析文件的输入流
        in = new FileInputStream(path+fileName);
        
        //2. 根据文件类型(xls、xlsx)创建一个工作簿,使用excel能操作的这边他都可以操作
        if(fileName.contains("xlsx")){
            workbook = new XSSFWorkbook(in);
        }else{
            workbook = new HSSFWorkbook(in);
        }

        //3. 得到表,第一个sheet
        sheet = workbook.getSheetAt(0);

        //设置存储list
        List<Coach> list = new ArrayList<Coach>();

		//这里对第一行标题不解析,如果要解析,那么就需要将索引值改写为0
        for(int rowIndex = 1; rowIndex < sheet.getPhysicalNumberOfRows(); rowIndex ++){
            //4. 得到行
            Row row = sheet.getRow(rowIndex);
            if (row == null){//非空判断
                continue;
            }
            Coach coach = new Coach();//创建coach对象
            for(int cellIndex = 0; cellIndex < row.getPhysicalNumberOfCells(); cellIndex ++){
                //5. 得到列
                Cell cell = row.getCell(cellIndex);
                if(cell==null){
                    continue;
                }
                int cellType = cell.getCellType();
                String cellValue = "";
                switch (cellType){
                    case HSSFCell.CELL_TYPE_STRING: //字符串
                        cellValue = cell.getStringCellValue();
                        break;
                    case HSSFCell.CELL_TYPE_BOOLEAN: //布尔
                        cellValue = String.valueOf(cell.getBooleanCellValue());
                        break;
                    case HSSFCell.CELL_TYPE_BLANK: //空
                        System.out.print("空!!");
                        break;
                    case HSSFCell.CELL_TYPE_NUMERIC: //数字(日期、普通数字)
                        if(HSSFDateUtil.isCellDateFormatted(cell)){//日期
                            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                            Date date = HSSFDateUtil.getJavaDate(cell.getNumericCellValue());
                            cellValue = sdf.format(date);
                        }else{ //普通数字
                            cell.setCellType(HSSFCell.CELL_TYPE_STRING);
                            cellValue = cell.toString();
                        }
                        break;
                    case HSSFCell.CELL_TYPE_ERROR: //错误
                        cellValue = "错误";
                        break;
                }
                DateFormat format=new SimpleDateFormat("yyyy-MM-dd");
                switch (cellIndex){
                    case 0://number
                        coach.setNumber((String) cellValue);
                        break;
                    case 1://name
                        coach.setName((String)cellValue);
                        break;
                    case 2://sex
                        coach.setSex((String)cellValue);
                        break;
                    case 3://courseNumber
                        coach.setCourseNumber((String)cellValue);
                        break;
                    case 4://birthday
                        coach.setBirthday(format.parse(cellValue));
                        break;
                    case 5://phone
                        coach.setPhone((String)cellValue);
                        break;
                    case 6://ResponsibleClass
                        coach.setResponsibleClass((String)cellValue);
                        break;
                    case 7://registrationDate
                        coach.setRegistrationDate(format.parse(cellValue));
                        break;
                    case 8://effectiveDeadline
                        coach.setEffectiveDeadline(format.parse(cellValue));
                        break;
                }
            }
            list.add(coach);
        }
        //输入流关闭
        in.close();
        //上传文件删除
        File fileDelete = new File(path+fileName);
        fileDelete.delete();
        
        return list;
    }
}

三、批量上传至服务器

Dao 层:

@Insert("<script>"  +
        "insert into coach(id, number, name, sex, courseNumber, birthday, phone, responsibleClass, registrationDate, effectiveDeadline) VALUES " +
        "<foreach collection='list' item='item' index='index' separator=','> " +
        "(null,#{item.number},#{item.name}, #{item.sex}, #{item.courseNumber}, #{item.birthday}, #{item.phone}, #{item.responsibleClass}, #{item.registrationDate}, #{item.effectiveDeadline}) " +
        "</foreach>" +
        "</script>")
void insertCoachOfBatch(List<Coach> coachList);

注:这里以个人项目中的 Coach 实体类对象进行举例,后文会给出 Coach 对象的实体类代码,读者做参考即可。


四、整体代码

前端 jsp:

<!--文件上传部分-->
<div class="modal fade" id="myModal-upload" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" data-backdrop="false">
	<div class="modal-dialog" role="document" id="uploadPopup">
		<div class="modal-content">
			<div class="modal-header">
				<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
				<h4 class="modal-title" id="myModalLabel-4">批量导入数据</h4>
			</div>
			<form class="form-horizontal" id="upload-form" action="${pageContext.request.contextPath}/admin/coach/upload" enctype="multipart/form-data" method="post">
				<div class="form-group">
					<label for="chooseFileUpload" class="col-sm-3 control-label" >选择文件</label>
					<div class="col-sm-9" >
						<input type="file" class="" id="chooseFileUpload" placeholder=""  name="upload" />
					</div>
				</div>
				<div class="form-group">
					<div class="col-xs-offset-4 col-sm-offset-4 col-xs-7 col-sm-7" style="color: red; text-align: right;">
						注意:指定文件格式!
					</div>
				</div>
			</form>
			<div class="modal-footer">
				<button type="button" class="btn btn-default" data-dismiss="modal"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span>&nbsp;关闭</button>
				<button type="button" id="btn_submit_upload" class="btn btn-primary" data-dismiss="modal">&nbsp;上传</button>
			</div>
		</div>
	</div>
</div>
<script>
	$(function (){
		//文件上传
		$('#uploadBtn').click(function () {
			$('#myModal-upload').modal();
		});
		$('#btn_submit_upload').click(function () {
			$('#upload-form').submit();
		});
	})
</script>

页面效果如下:
在这里插入图片描述


Controller层:

@Controller
@RequestMapping("/admin/coach")
public class CoachController {

	@Autowired
    private CoachService coachService;
    

    @RequestMapping(path = "/upload")
    public String fileUpload(HttpServletRequest request, MultipartFile upload) throws Exception {
        //使用 fileupload 组件完成文件上传
        String path = request.getSession().getServletContext().getRealPath("/upload/");//文件的上传位置
        //判断该路径是否存在
        File file = new File(path);
        if(!file.exists()){
            //创建该文件夹
            file.mkdirs();
        }
        //说明上传文件项
        //获取上传文件的名称
        String fileName = upload.getOriginalFilename();
        //完成文件上传
        upload.transferTo(new File(path, fileName));
        coachService.parsingExcel(path, fileName);

        return "admin/fileUploadSuccess";
    }
}

Service层:

@Service("coachService")
public class CoachServiceImpl implements CoachService {

    @Autowired
    private CoachDao coachDao;
	
	@Override
    public void parsingExcel(String path, String fileName) throws IOException, ParseException {
        List<Coach> coachList = ParseExcelUtil.parseCoachExcel(path, fileName);
        coachDao.insertCoachOfBatch(coachList);
    }
}

Coach实体类 :

import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;

public class Coach implements Serializable {

    private static final long serialVersionUID = 1L;
    private Integer id;
    private String number;
    private String name;
    private String sex;
    private String courseNumber;
    private String phone;
    private String responsibleClass;

    @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date birthday;

    @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
    @DateTimeFormat(pattern = "yyyy-MM-dd") //添加数据的时候防止格式不符
    private Date registrationDate;

    @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date effectiveDeadline;

    //一对一关联
    private Course course;


    public static long getSerialVersionUID() {
        return serialVersionUID;
    }

    public Integer getId() {
        return id;
    }

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

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getCourseNumber() {
        return courseNumber;
    }

    public void setCourseNumber(String courseNumber) {
        this.courseNumber = courseNumber;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getResponsibleClass() {
        return responsibleClass;
    }

    public void setResponsibleClass(String responsibleClass) {
        this.responsibleClass = responsibleClass;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public Date getRegistrationDate() {
        return registrationDate;
    }

    public void setRegistrationDate(Date registrationDate) {
        this.registrationDate = registrationDate;
    }

    public Date getEffectiveDeadline() {
        return effectiveDeadline;
    }

    public void setEffectiveDeadline(Date effectiveDeadline) {
        this.effectiveDeadline = effectiveDeadline;
    }

    public Course getCourse() {
        return course;
    }

    public void setCourse(Course course) {
        this.course = course;
    }

    @Override
    public String toString() {
        return "Coach{" +
                "id=" + id +
                ", number='" + number + '\'' +
                ", name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", courseNumber='" + courseNumber + '\'' +
                ", phone='" + phone + '\'' +
                ", responsibleClass='" + responsibleClass + '\'' +
                ", birthday=" + birthday +
                ", registrationDate=" + registrationDate +
                ", effectiveDeadline=" + effectiveDeadline +
                ", course=" + course +
                '}';
    }
}

五、整体效果演示

在这里插入图片描述


六、补充

  当我们在上传文件的时候,对日期类型解析会失败。因为 POI 解析的是指定格式的表格,所以对日期字符串格式识别不出,因此需要对日期字段的格式进行指定类型为日期。

在这里插入图片描述


  对 POI 解析 EXCEL 表格的相关操作,就先解析到这里。POI 解析EXCEL存在一定的局限性,比如要将数据所对应的列提前指定等。 如果读者还对 POI 解析 EXCEL 表格操作中出现问题,欢迎大家在评论区留言哦~

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

应用 POI 解析 Excel 表格并批量上传到数据库 的相关文章

随机推荐

  • YOLOv5+单目测距(python)

    YOLOv5 单目测距 python 1 相关配置 2 测距原理 3 相机标定 3 1 标定方法1 3 2 标定方法2 4 相机测距 4 1 测距添加 4 2 细节修改 可忽略 4 3 主代码 5 实验效果 相关链接 1 YOLOV7 单目
  • python ttk Treeview的插入、清空、各种点击事件、获取条目值、标题单击排序

    昨天整了一天Tkinter的treeview 发现中文的教程乃至提问都很少 其中两个问题的解决都是靠steakoverflow上找到的 在这里放出来我遇到并解决的问题 大家以后可能遇到的话就能省点事了 插入方法 import tkinter
  • 第二章-Kali安装

    目录 2 Kali Linux安装 硬盘安装 虚拟机安装 01硬盘安装 02DOCKER 03虚拟机安装 3 Kali Linux 安装 持久加密USB安装 熟悉环境 熟悉BASH命令 01 持久加密USB安装 1 02 持久加密USB安装
  • 专注于开源技术的研究与应用由Tencent://Message协议想到的一个解决方案

    源代码下载 http files cnblogs com phinecos HelloWorldProtocal rar 前天在BruceZhang 的一篇博文 求助 如何在ASP页面中调用Winform程序呢 中回答了他提出的问题 但细想
  • jsp调用证书类ocx控件问题

    1 先注册ocx 本次使用的方式是先将我调用的两个控件打包成 CAB文件 然后做成一个exe让用户去下载注册 2 jsp页面上使用 进行调用 ps clsid可以在注册表中找到 id是自己定义的 因为控件在第一步已经注册到注册表里 code
  • 重学Elasticsearch7(来源官方文档)

    一 开篇总览 1 bulk操作最好请求体数据大小在5m 15m 2 由于要给文件系统缓存留下足够空间 es的jvm堆大小不要超过服务器可用内存空间的一半 二 聚合 1 在聚合时 missing字段可以给没有该字段的文档以默认值 2 带权重的
  • html登录页面整理

    img src data image png base64 iVBORw0KGgoAAAANSUhEUgAAAycAAAJGCAYAAABBdvriAAAgAElEQVR4Aey9W5okN5KsWUz2qmaxs7zzNEvoSo78Ii
  • java自动化测试语言高级之Java 9 新特性

    java自动化测试语言高级之Java 9 新特性 文章目录 java自动化测试语言高级之Java 9 新特性 Java 9 新特性 Java 9 新特性 Java 9 发布于 2017 年 9 月 22 日 带来了很多新特性 其中最主要的变
  • 内嵌模式搭建Hive

    在此之前已经搭建好了一个三台机器的hadoop集群 https blog csdn net QYHuiiQ article details 123055389 spm 1001 2014 3001 5501 接下来在此基础上搭建hive 下
  • (C++)GDAL学习笔记——1 均值滤波和中值滤波

    就要开始研究生生活了 这个暑假要学一下GDAL相关的知识 这里将中间完成的一些东西Mark下来 方便自己以后回顾 任务 利用Vc 编写一个3 3的均值滤波或中值滤波程序 代码 注 此次试验用到的影像为波段数为1的tif格式影像 主函数 in
  • 2022 年 MathorCup 高校数学建模挑战赛——大数据竞赛赛道 赛道 B:北京移动用户体验影响因素研究

    问题 1 根据附件 1 和附件 2 分别研究影响客户语音业务和上网业务 满意度的主要因素 并给出各因素对客户打分影响程度的量化分析和结果 附件 1 2 中各字段的解释说明见附件 5 问题一本质就是特征筛选问题 而且要给出各特征影响程度的量化
  • node实现发送邮件和上传文件功能

    文章目录 node实现发送邮件带附件 node 是什么 下载 文件结构 index html文件 nodemails js文件 node实现发送邮件带附件 记录下我前不久刚刚接触过的node用来实现发送邮件和上传文件图片功能 希望能帮到和我
  • L2-021 点赞狂魔分数

    微博上有个 点赞 功能 你可以为你喜欢的博文点个赞表示支持 每篇博文都有一些刻画其特性的标签 而你点赞的博文的类型 也间接刻画了你的特性 然而有这么一种人 他们会通过给自己看到的一切内容点赞来狂刷存在感 这种人就被称为 点赞狂魔 他们点赞的
  • vector扩容

    扩容原理 vector以连续的数组存放数据 当vector空间已满时会申请新的空间并将原容器中的内容拷贝到新空间中 并销毁原容器 存储空间的重新分配会导致迭代器失效 因为分配空间后需要进行拷贝 编译器会预分配更多空间以减少发生拷贝影响程序效
  • 音视频绕不开的话题之WebRTC

    什么是WebRTC 闲来无事 我们今天探讨下音视频绕不开的一个话题 WebRTC WebRTC之于音视频行业 无异于FFMpeg 可以说WebRTC的开源 让音视频行业大跨步进入发展快车道 WebRTC是一个支持实时音视频通信的开源项目 它
  • Vue3项目开发使用技巧setup

  • 【第18例】IPD进阶:跨部门团队 —— SPDT超级产品开发团队

    目录 简介 专栏目录 详细内容 相关专栏推荐 CSDN学院 作者简介 简介 今天 IPD体系进阶100例 就更新到了第 18 例 SPDT 是英文 Super Product Development Team 的英文首字母简称
  • java网络编程:9、基于TCP的socket编程(二)服务器端循环监听接收多个客户端_多线程服务器程序

    声明 本教程不收取任何费用 欢迎转载 尊重作者劳动成果 不得用于商业用途 侵权必究 文章目录 一 核心代码编写 1 服务器端程序的编写 2 客户端程序的编写 3 测试打印输出 二 系列文章 java网络编程 上篇讲了基于tcp的编程的一些基
  • 【Python-利用动态二维码传输文件(七)】计算文件传输速度,以KB/s形式显示在Tkinter界面。

    上一篇文章实现了动态二维码文件接收端的基本功能 但只能显示接收数据的完成度 不能显示接收速度 本篇文章研究怎么计算文件传输速度 并以KB s形式显示在Tkinter界面 方便以后调试和优化代码 一 程序效果展示 可以看到右下角有统计发送速度
  • 应用 POI 解析 Excel 表格并批量上传到数据库

    在日常生活中 我们时常会遇到添加用户之类的操作 但是这类操作 只能一位一位的添加 遇到向我这种强迫症晚期患者 会被烦死 那么应用 POI 解析含有用户信息的 EXCEL 表格会省很多时间 本文针对解析 EXCEL 表格以及将表格上的内容批量