spring boot如何使用POI读取Excel文件
作者:代码猫 发布时间:2022-09-19 21:26:33
标签:springboot,POI,Excel文件
spring boot 使用POI读取Excel文件
Excel文件目录
Excel模板文件存了resourse目录下,如下图:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.16</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.16</version>
</dependency>
重要说明
如果是xls格式,使用HSSFWorkbook,HSSFSheet,HSSFRow来进行相关操作
如果是xlsx格式,使用XSSFWorkbook,XSSFSheet,XSSFRow来进行相关操作
读取Excel文件
// 定义一个数据格式化对象
XSSFWorkbook wb = null;
try {
//excel模板路径
File cfgFile = ResourceUtils.getFile(ResourceUtils.CLASSPATH_URL_PREFIX + "static/ExcelTemplate/ContradictionMatrix.xlsx");
InputStream in = new FileInputStream(cfgFile);
//读取excel模板
wb = new XSSFWorkbook(in);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
获取sheet表格及读写单元格内容
//获取sheet表格,及读取单元格内容
XSSFSheet sheet = null;
try{
sheet = wb.getSheetAt(0);
//先将获取的单元格设置为String类型,下面使用getStringCellValue获取单元格内容
//如果不设置为String类型,如果单元格是数字,则报如下异常
//java.lang.IllegalStateException: Cannot get a STRING value from a NUMERIC cell
sheet.getRow(2).getCell(2).setCellType(CellType.STRING);
//读取单元格内容
String cellValue = sheet.getRow(2).getCell(2).getStringCellValue();
//添加一行
XSSFRow row = sheet.createRow(1); //第2行开始写数据
row.setHeight((short)400); //设置行高
//向单元格写数据
row.createCell(1).setCellValue("名称");
}
catch (Exception e){
e.printStackTrace();
}
合并单元格
使用下面的语句合并单元格:
sheet.addMergedRegion(new CellRangeAddress(0,2,15,18));
看一下CellRangeAddress的构造函数:
/**
* Creates new cell range. Indexes are zero-based.
*
* @param firstRow Index of first row
* @param lastRow Index of last row (inclusive), must be equal to or larger than {@code firstRow}
* @param firstCol Index of first column
* @param lastCol Index of last column (inclusive), must be equal to or larger than {@code firstCol}
*/
public CellRangeAddress(int firstRow, int lastRow, int firstCol, int lastCol) {
super(firstRow, lastRow, firstCol, lastCol);
if (lastRow < firstRow || lastCol < firstCol)
throw new IllegalArgumentException("lastRow < firstRow || lastCol < firstCol");
}
SpringBoot解析Excel
现在很多web应用中,导入excel导出excel很常见,这篇文章就讲讲导入excel文件。
以批量导入课程为例
首先加入需要的jar包
<!--解析excel-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>RELEASE</version>
</dependency>
数据库中创建一个表course
DROP TABLE IF EXISTS `course`;
CREATE TABLE `course` (
`course_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '课程id',
`course_code` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '课程代码',
`course_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '课程名称',
`teacher_id` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '教师id',
`course_time` date NOT NULL DEFAULT '1996-01-01' COMMENT '开课时间',
`class_room` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '开课地点',
`course_week` int(5) UNSIGNED NOT NULL DEFAULT 0 COMMENT '课程学时',
`course_type` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '必修课' COMMENT '课程类型',
`college_id` int(11) UNSIGNED NOT NULL COMMENT '所属院系id',
`score` int(5) UNSIGNED NOT NULL DEFAULT 0 COMMENT '学分',
`is_on` tinyint(2) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否开启了选课,默认0未开启',
PRIMARY KEY (`course_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '课程表' ROW_FORMAT = Dynamic;
新建一个ExcelUtil.java
/**
* excel工具类
*/
public class ExcelUtils {
private static Logger logger = LoggerFactory.getLogger(ExcelUtils.class);
/**
* 课程excel
* @param in
* @param fileName
* @return
* @throws Exception
*/
public static List getCourseListByExcel(InputStream in, String fileName) throws Exception {
List list = new ArrayList<>();
// 创建excel工作簿
Workbook work = getWorkbook(in, fileName);
if (null == work) {
throw new Exception("创建Excel工作薄为空!");
}
Sheet sheet = null;
Row row = null;
Cell cell = null;
for (int i = 0; i < work.getNumberOfSheets(); i++) {
sheet = work.getSheetAt(i);
if(sheet == null) {
continue;
}
// 滤过第一行标题
for (int j = sheet.getFirstRowNum(); j <= sheet.getLastRowNum(); j++) {
row = sheet.getRow(j);
if (row == null || row.getFirstCellNum() == j) {
continue;
}
List<Object> li = new ArrayList<>();
for (int y = row.getFirstCellNum(); y < row.getLastCellNum(); y++) {
cell = row.getCell(y);
// 日期类型转换
if(y == 3) {
//cell.setCellType(CellType.STRING);
double s1 = cell.getNumericCellValue();
Date date = HSSFDateUtil.getJavaDate(s1);
li.add(date);
continue;
}
li.add(cell);
}
list.add(li);
}
}
work.close();
return list;
}
/**
* 判断文件格式
* @param in
* @param fileName
* @return
*/
private static Workbook getWorkbook(InputStream in, String fileName) throws Exception {
Workbook book = null;
String filetype = fileName.substring(fileName.lastIndexOf("."));
if(".xls".equals(filetype)) {
book = new HSSFWorkbook(in);
} else if (".xlsx".equals(filetype)) {
book = new XSSFWorkbook(in);
} else {
throw new Exception("请上传excel文件!");
}
return book;
}
}
这里主要注意一下上面的日期转换,在excel中的日期,通过Java读出来之后,变成了26 四月 2019这样的形式,而数据库中我们的字段类型为date,所以总是插入失败。
上面我的写法直接是知道那个字段是Date类型,所以直接使用y==3,这样写可复用性很差。
接下来直接看和数据库交互的逻辑代码
/**
* 通过excel文件,批量增加课程
* @param request
* @return
* @throws Exception
*/
@PostMapping("/upload/course")
public String uploadCourseExcel(HttpServletRequest request) {
MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) request;
MultipartFile file = multipartHttpServletRequest.getFile("courseFile");
if(file.isEmpty()) {
return "redirect:/admin/course/list";
}
try {
InputStream inputStream = file.getInputStream();
List<List<Object>> list = ExcelUtils.getCourseListByExcel(inputStream, file.getOriginalFilename());
inputStream.close();
for (int i = 0; i < list.size(); i++) {
List<Object> courseList = list.get(i);
Course course = new Course();
course.setCourseCode(courseList.get(0).toString());
course.setCourseName(courseList.get(1).toString());
// 通过教师姓名查教师id
String teacherId = teacherService.getTeacByName(courseList.get(2).toString());
// 教师信息错误,直接跳过这条记录
if(teacherId == null) {
continue;
}
course.setTeacherId(teacherId);
// 格式化时间
Date date = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US).parse(courseList.get(3).toString());
course.setCourseTime(new SimpleDateFormat("yyyy-MM-dd").parse(new SimpleDateFormat("yyyy-MM-dd").format(date)));
course.setClassRoom(courseList.get(4).toString());
course.setCourseWeek(Integer.parseInt(new DecimalFormat("0").format(Double.parseDouble(courseList.get(5).toString()))));
course.setCourseType(courseList.get(6).toString());
// 通过院系名称查询院系id
Integer collegeId = collegeService.getCollegeByName(courseList.get(7).toString());
// 院系有误,直接跳过这条记录
if(collegeId == null || collegeId == 0) {
continue;
}
course.setCollegeId(collegeId);
course.setScore(Integer.parseInt(new DecimalFormat("0").format(Double.parseDouble(courseList.get(8).toString()))));
// 默认不开启选课
course.setIsOn(0);
logger.error("course = " + course);
// 判断课程是否重复(同一门课程可以有多个教师教师course_code, course_name, teacher_id联合)
Integer courseId = null;
courseId = courseService.getCourseByThree(course);
// 存在重复的
if(courseId != null) {
// 跳过不添加
continue;
}
// 执行插入操作
courseService.addCourse(course);
}
} catch (Exception e) {
return "redirect:/admin/course/list";
}
return "redirect:/admin/course/list";
}
可以看到,我又对时间类型进行了处理,才能最终插入数据库
// 格式化时间
Date date = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US).parse(courseList.get(3).toString());
course.setCourseTime(new SimpleDateFormat("yyyy-MM-dd").parse(new SimpleDateFormat("yyyy-MM-dd").format(date)));
同时,在excel中的整数类型,取出来之后就会变成Double类型比如5变成5.0,所以我对此也进行了处理
course.setCourseWeek(Integer.parseInt(new DecimalFormat("0").format(Double.parseDouble(courseList.get(5).toString()))));
最后调用代码进行插入操作。
看看前端代码
<button class="btn btn-default col-md-2" style="margin-top: 20px">
<a data-toggle="modal" href="#uploadExcel" rel="external nofollow" role="button" style="color: black; text-decoration: none">
批量添加<sapn class="glyphicon glyphicon-plus"/>
</a>
</button>
<!--批量添加模态框-->
<div class="modal fade" tabindex="-1" role="dialog" id="uploadExcel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<form class="form-horizontal" role="form" th:action="@{/admin/upload/course}"
enctype="multipart/form-data" method="post">
<div class="modal-body">
请选择文件:<input type="file" name="courseFile">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
<button type="submit" class="btn btn-success">添加</button>
</div>
</form>
</div>
</div>
</div>
这里我通过button唤醒一个模态框来添加
最后测试结果
来源:https://www.cnblogs.com/codecat/p/10948120.html
0
投稿
猜你喜欢
- shiro是一个权限框架,具体的使用可以查看其官网 http://shiro.apache.org/ 它提供了很方便的权限认证和
- 泛型1、简单泛型泛型的主要目的之一就是用来指定容器要持有什么类型的对象,而且由编译器来保证类型的正确性。泛型暂时不指定类型,在使用时决定具体
- 一、 搭建struts2环境在myeclipse下,右击项目->MyEclipse->Project Facets->in
- 定义享元模式(FlyWeight Pattern),也叫蝇量模式,运用共享技术,有效的支持大量细粒度的对象,享元模式就是池技术的重要实现方式
- 一、创建项目创建一个简单的Java项目,其中Main.java为主函数,包含main方法:二、完成JAR配置进入File->Proje
- 本文实例为大家分享了Spring MVC接口防数据篡改和重复提交的具体代码,供大家参考,具体内容如下一、自定义一个注解,此注解可以使用在方法
- 1. 什么是λ表达式λ表达式本质上是一个匿名方法。让我们来看下面这个例子: public int add(int x, int
- Guava Cache:⾕歌开源缓存框架Guava Cache是在内存中缓存数据,相比较于数据库或redis存储,访问内存中的数据会更加高效
- 有时候因为安全问题,需要把配置文件的中数据库用户名密码由明文改成密文,大多数其实是为了应付甲方而已。1.pom.xml引入依赖<dep
- 前言:java.util.Set接口和 java.util.List接口一样,同样继承自 Collection接口,它与
- 1. 定义TreeMap的排序方法使用Comparator对象作为参数需要注意的是:排序方法是针对键的,而不是值的。如果想针对值,需要更麻烦
- 记录一下工作流的在Springboot中的使用,,顺便写个demo,概念,什么东西的我就不解释了,如有问题欢迎各位大佬指导一下。1.创建sp
- 1 问题手写一个程序,完成List集合对象的逆序遍历2 方法创建List接口的多态对象向创建好list集合添加元素使用hasPrevious
- 一. 关键字Java中的关键字是由特定的单词组成,单词全为小写字母,每个都有特殊的含义,其实Java关键字也就那几十个,这个不需要背,以后都
- Comparable 比较器,内置定义的比较方法,实现比较 较简单Comparator 策略模式,需要定义不同的策略和比较的对象,实现比较
- 第一步:下载JDK地址:http://www.oracle.com/technetwork/java/javase/downloads/in
- 项目介绍springboot搭建的访客管理系统,针对高端基地做严格把控来访人员信息管理,用户后端可以设置多个管理员帐号,给予不同部门的管理层
- 1)打开idea,开始创建SpringBoot项目2)选择 Spring Initializr ,选择合适的jdk版本,点击Next在操作到
- 概况Java的Long类主要的作用就是对基本类型long进行封装,提供了一些处理long类型的方法,比如long到String类型的转换方法
- 本地仓库主要是一种缓存,当你使用远程仓库中下载组件后,它下一次会优先从本地进行加载,一般位于USER_HOME/.m2目录下,我们自己也可以