EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。
官网:https://www.yuque.com/easyexcel/doc/easyexcel
github地址:https://github.com/alibaba/easyexcel
Java解析、生成Excel比较有名的框架有Apache poi、jxl,但他们都存在一个严重的问题就是非常的耗内存。
EasyExcel 重写了poi,使一个3M的excel只需要几M内存,并且再大的excel不会出现内存溢出。
64M内存1分钟内读取75M(46W行25列)的Excel。
修改pom文件
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
dependency>
dependencies>
项目名:zx-test-excel
修改pom,添加依赖
<dependencies>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>easyexcelartifactId>
<version>2.2.6version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
dependency>
dependencies>
package com.czxy.zx.demo01;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.util.Date;
/**
* Created by liangtong.
*/
@Data
public class Student {
@ExcelProperty("编号")
private String id;
@ExcelProperty("姓名")
private String name;
@ExcelProperty("年龄")
private Integer age;
@ExcelProperty("电话")
private String telephone;
@ExcelProperty("邮箱")
private String email;
@ExcelProperty("生日")
private Date brithday;
}
package com.czxy.zx.demo01;
import org.junit.jupiter.api.Test;
/**
* @author 桐叔
* @email [email protected]
*/
public class TestExcel {
/**
* 获得根路径
* @return
*/
public String getPath() {
return this.getClass().getResource("/").getPath();
}
@Test
public void testPath() {
// 测试文件路径
String path = getPath() + "student_demo.xls";
System.out.println(path);
}
}
~~~### 1.4.3 写操作
~~~java
/**
* 准备数据
* @return
*/
private List<Student> getData(){
List<Student> list = new ArrayList<Student>();
for(int i = 0 ; i < 10 ; i ++){
Student student = new Student();
student.setId("stu" + i);
student.setName("wang" + i);
student.setAge( 18 + i );
student.setTelephone("1361234" + i);
student.setEmail("wang" + i + "@czxy.com");
student.setBrithday(new Date());
list.add(student);
}
return list;
}
@Test
public void testWrite(){
String file = getPath() + "student_demo.xls";
//EasyExcel.write(位置,对象).sheet("表名").doWrite(数据);
EasyExcel.write(file,Student.class).sheet("Java34").doWrite(getData());
}
处理类:
AnalysisEventListener
接口package com.czxy.zx.demo01;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.czxy.zx.domain.Student;
/**
* @author 桐叔
* @email [email protected]
*/
public class StudentListener extends AnalysisEventListener<Student> {
@Override
public void invoke(Student student, AnalysisContext analysisContext) {
System.out.println(student);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
System.out.println("解析完成");
}
}
测试
@Test
public void testRead(){
String file = getPath() + "student_demo.xls";
//EasyExcel.read(文件, 封装对象, 处理类).sheet("表").doRead();
EasyExcel.read(file, Student.class, new StudentListener()).sheet("Java34").doRead();
}
package com.czxy.zx.demo02;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import java.util.Date;
/**
* @author 桐叔
* @email [email protected]
*/
@Data
@ContentRowHeight(10)
@HeadRowHeight(20) //行高
@ColumnWidth(25) //列宽
public class Student2 {
@ExcelProperty("编号")
private String id;
@ExcelProperty({"基本信息","姓名"}) //复制表头
private String name;
@ExcelProperty({"基本信息","年龄"})
private Integer age;
@ExcelProperty("电话")
private String telephone;
@ExcelProperty("邮箱")
private String email;
@ExcelProperty("生日")
@DateTimeFormat("yyyy年MM月dd日")
private Date brithday;
}
package com.czxy.zx.demo02;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.czxy.zx.demo01.Student;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @author 桐叔
* @email [email protected]
*/
public class TestExcel2 {
/**
* 获得根路径
* @return
*/
public String getPath() {
return this.getClass().getResource("/").getPath();
}
/**
* 准备数据
* @return
*/
private List<Student2> getData(Integer flag){
List<Student2> list = new ArrayList<Student2>();
for(int m = 0 ; m < 10 ; m ++){
String i = "" + flag + m ;
Student2 student = new Student2();
student.setId("stu" + i);
student.setName("wang" + i);
student.setAge( 18 );
student.setTelephone("1361234" + i);
student.setEmail("wang" + i + "@czxy.com");
student.setBrithday(new Date());
list.add(student);
}
return list;
}
@Test
public void testMoreSheetWrite(){
String file = getPath() + "student_demo2.xls";
ExcelWriter excelWriter = EasyExcel.write(file).build();
for (int i = 0; i < 5; i++) {
WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).head(Student2.class).build();
// 分页去数据库查询数据 这里可以去数据库查询每一页的数据
List<Student2> data = getData(i);
excelWriter.write(data, writeSheet);
}
excelWriter.finish();
}
}
具有缓存处理类
package com.czxy.zx.demo02;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import java.util.ArrayList;
import java.util.List;
/**
* Created by liangtong.
*/
public class Student2Listener extends AnalysisEventListener<Student2> {
// 批量操作数
private static final int BATCH_COUNT = 10;
// 用于缓存信息
private List<Student2> cache = new ArrayList<Student2>();
public void invoke(Student2 student, AnalysisContext analysisContext) {
//保存学生信息
cache.add(student);
if(cache.size() >= BATCH_COUNT){
// 保存数据
saveData();
}
}
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
//最后的不够 BATCH_COUNT 倍数
saveData();
}
private void saveData() {
// 集合不为空
if(! cache.isEmpty()) {
// 处理缓存数据
System.out.println(cache);
// 清空缓存
cache.clear();
}
}
}
读操作
@Test
public void testMoreRead(){
String file = getPath() + "student_demo2.xls";
//EasyExcel.read(文件, 封装对象, 处理类).sheet("表").doRead();
ExcelReader excelReader = EasyExcel.read(file, Student2.class, new Student2Listener()).build();
// 确定需要解析的sheet
for (int i = 0; i < 5; i++) {
ReadSheet readSheet = EasyExcel.readSheet("模板" + i).build();
excelReader.read(readSheet);
}
excelReader.finish();
}
CREATE DATABASE zx_edu_course;
USE zx_edu_course;
CREATE TABLE `edu_subject` (
`id` VARCHAR(32) NOT NULL PRIMARY KEY COMMENT '课程科目ID',
`title` VARCHAR(10) NOT NULL COMMENT '科目名称',
`parent_id` VARCHAR(32) NOT NULL DEFAULT '0' COMMENT '父ID',
`sort` INT(10) NOT NULL DEFAULT 0 COMMENT '排序字段',
`gmt_create` DATETIME NOT NULL COMMENT '创建时间',
`gmt_modified` DATETIME NOT NULL COMMENT '更新时间'
) COMMENT = '课程科目';
INSERT INTO `edu_subject` VALUES ('1', '云计算', '0', 0, '2020-06-26 09:41:21', '2020-02-20 23:25:58');
INSERT INTO `edu_subject` VALUES ('2', '系统/运维', '0', 0, '2020-02-20 23:29:59', '2020-02-20 23:29:59');
INSERT INTO `edu_subject` VALUES ('3', '数据库', '0', 0, '2020-02-20 23:30:13', '2020-02-20 23:30:13');
INSERT INTO `edu_subject` VALUES ('4', '服务器', '0', 0, '2020-02-20 23:30:19', '2020-02-20 23:30:19');
INSERT INTO `edu_subject` VALUES ('5', 'MySQL', '3', 1, '2020-02-20 23:30:13', '2020-02-20 23:30:13');
INSERT INTO `edu_subject` VALUES ('6', 'Oracle', '3', 2, '2020-02-20 23:30:13', '2020-02-20 23:30:13');
INSERT INTO `edu_subject` VALUES ('7', 'Tomcat', '4', 1, '2020-02-20 23:30:13', '2020-02-20 23:30:13');
INSERT INTO `edu_subject` VALUES ('8', 'Nginx ', '4', 2, '2020-02-20 23:30:13', '2020-02-20 23:30:13');
INSERT INTO `edu_subject` VALUES ('9', 'MySQL优化', '5', 1, '2020-02-20 23:30:13', '2020-02-20 23:30:13');
项目名:zx-service-course20
pom文件
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-hystrixartifactId>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>${mybatis.plus.version}version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
<dependency>
<groupId>com.czxy.zxgroupId>
<artifactId>zx-common20artifactId>
<version>1.0-SNAPSHOTversion>
dependency>
<dependency>
<groupId>com.czxy.zxgroupId>
<artifactId>zx-domain20artifactId>
<version>1.0-SNAPSHOTversion>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-mailartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-amqpartifactId>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.73version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>easyexcelartifactId>
<version>2.2.6version>
dependency>
dependencies>
yml文件
# 服务端口号
server:
port: 9020
# 服务名
spring:
application:
name: course-service
datasource:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/zx_edu_course?useUnicode=true&characterEncoding=utf8
username: root
password: 1234
druid: #druid 连接池配置
initial-size: 1 #初始化连接池大小
min-idle: 1 #最小连接数
max-active: 20 #最大连接数
test-on-borrow: true #获取连接时候验证,会影响性能
redis:
database: 0 #数据库索引,取值0-15,表示16个库可选择
host: 127.0.0.1 #服务器地址
port: 6379 #服务器连接端口号
mail:
host: smtp.126.com #发送邮件服务器
username: [email protected] #账号
password: 1qaz2wsx #密码
default-encoding: UTF-8 #默认编码时
rabbitmq:
host: 127.0.0.1
port: 5672
username: guest
passowrd: guest
virtualHost: /
devtools:
restart:
enabled: true #设置开启热部署
additional-paths: src/main/java #重启目录
exclude: WEB-INF/**
freemarker:
cache: false #页面不加载缓存,修改即时生效
#eureka配置
eureka:
client:
service-url:
defaultZone: http://localhost:10086/eureka
instance: #web页面显示效果和访问路径
instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${server.port}
prefer-ip-address: true
#开启log4j打印SQL语句
logging:
level:
com:
czxy:
mapper: debug
# feign远程调用,开启熔断
feign:
hystrix:
enabled: true
# mp日志打印
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
启动类
package com.czxy.zx;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
/**
* @author 桐叔
* @email [email protected]
*/
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class ZxCourseServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ZxCourseServiceApplication.class,args);
}
}
创建JavaBean
package com.czxy.zx.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 课程科目(EduSubject)表实体类
*
* @author 桐叔
*/
@Data
@TableName("edu_subject")
public class EduSubject{
@TableId(type = IdType.ASSIGN_UUID)
//课程科目ID
private String id;
//科目名称
private String title;
//父ID
private String parentId;
//排序字段
private Integer sort;
//创建时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private Date gmtCreate;
//更新时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private Date gmtModified;
@TableField(exist = false)
private List<EduSubject> children; // = new ArrayList<>();
}
创建mapper
package com.czxy.zx.course.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.czxy.zx.domain.EduSubject;
import org.apache.ibatis.annotations.Mapper;
/**
* @author 桐叔
* @email [email protected]
*/
@Mapper
public interface EduSubjectMapper extends BaseMapper<EduSubject> {
}
接口
package com.czxy.zx.course.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.czxy.zx.domain.EduSubject;
/**
* @author 桐叔
* @email [email protected]
*/
public interface EduSubjectService extends IService<EduSubject> {
}
实现类
package com.czxy.zx.course.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.czxy.zx.course.mapper.EduSubjectMapper;
import com.czxy.zx.course.service.EduSubjectService;
import com.czxy.zx.domain.EduSubject;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* @author 桐叔
* @email [email protected]
*/
@Service
@Transactional
public class EduSubjectServiceImpl extends ServiceImpl<EduSubjectMapper, EduSubject> implements EduSubjectService {
}
创建controller
package com.czxy.zx.course.controller;
import com.czxy.zx.course.service.EduSubjectService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @author 桐叔
* @email [email protected]
*/
@RestController
@RequestMapping("/subject")
public class EduSubjectController {
@Resource
private EduSubjectService eduSubjectService;
}
/** When your routing table is too long, you can split it into small modules **/
import Layout from '@/layout'
const courseRouter = {
path: '/course', // 当前模块前缀路径,必须以/开头
component: Layout, // 采用布局组件显示当前模块【默认】
redirect: '/course/subjectList', // “教师管理”默认显示路由
name: '课程管理', // 路由名称
meta: {
title: '课程管理', // 一级菜单名称,children.length==0 隐藏
icon: 'table' // 一级菜单图标,children.length==0 隐藏
},
children: [
{
path: 'subjectList',
component: () => import('@/views/edu/course/subjectList.vue'),
name: '科目列表',
meta: { title: '科目列表', icon: 'list' } //二级菜单名称
}
]
}
export default courseRouter
package com.czxy.zx.course.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.czxy.zx.course.service.EduSubjectService;
import com.czxy.zx.domain.EduSubject;
import com.czxy.zx.vo.BaseResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author 桐叔
* @email [email protected]
*/
@RestController
@RequestMapping("/subject")
public class EduSubjectController {
@Resource
private EduSubjectService eduSubjectService;
@GetMapping
public BaseResult findAll() {
//1 查询所有
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.orderByAsc("parent_id");
List<EduSubject> list = eduSubjectService.list(queryWrapper);
//2 处理父子关系
List<EduSubject> resultList = new ArrayList<>();
Map<String,EduSubject> cache = new HashMap<>();
list.forEach(eduSubject -> {
// 获得父
EduSubject parentEduSubject = cache.get(eduSubject.getParentId());
// 如果没有父表示第一层,如果有父追加
if(parentEduSubject != null) {
// 如果有孩子,判断父对象的集合
List<EduSubject> temp = parentEduSubject.getChildren();
if(temp == null) {
parentEduSubject.setChildren(new ArrayList<>());
}
// 将孩子添加到父对象的集合中
parentEduSubject.getChildren().add(eduSubject);
} else {
resultList.add(eduSubject);
}
// 缓存当前
cache.put(eduSubject.getId(),eduSubject);
});
return BaseResult.ok("查询成功", resultList);
}
}
import axios from '@/utils/request'
// 查询所有课程科目
export function findAllSub() {
return axios.get('/course-service/subject');
}
@/views/edu/course/subjectList.vue
{{ row.gmtCreate | parseTime('{y}-{m}-{d} {h}:{i}') }}
{{ row.gmtModified | parseTime('{y}-{m}-{d} {h}:{i}') }}
修改
删除
使用 upload组件
点击上传
只能上传xls或xlsx文件,且不超过500kb
声明变量
data() {
return {
fileList: [], //上传文件列表
updateUrl: process.env.VUE_APP_BASE_API + '/course-service/subject/upload', //上传路径
}
},
编写处理函数
handleExceed(files, fileList) { // 超出个数限制
this.$message.warning(`当前选择1个文件`);
},
beforeUpload(file) { // 上传文件之前
// 是否是 xlsx 文件(2003)
const isXlsx = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
// 是否是 xls 文件(2010)
const isXls = file.type === 'application/vnd.ms-excel'
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isXlsx && !isXls) {
this.$message.error('上传文件不是excel文件!');
}
if (!isLt2M) {
this.$message.error('上传文件大小不能超过 2MB!');
}
return (isXlsx || isXls) && isLt2M;
},
handleRemove(file, fileList) { // 文件列表移除文件
console.log(file, fileList);
},
handleSuccess(response, file, fileList) { // 文件上传成功
// 成功提示
this.$message.success(response.message)
// 刷新
this.findAllSubject()
}
{{ row.gmtCreate | parseTime('{y}-{m}-{d} {h}:{i}') }}
{{ row.gmtModified | parseTime('{y}-{m}-{d} {h}:{i}') }}
修改
删除
点击上传
只能上传xls或xlsx文件,且不超过500kb
package com.czxy.zx.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 课程科目(EduSubject)表实体类
*
* @author 桐叔
*/
@Data
@TableName("edu_subject")
public class EduSubject{
@TableId(type = IdType.ASSIGN_UUID)
//课程科目ID
private String id;
//科目名称
private String title;
//父ID
private String parentId;
//排序字段
private Integer sort;
//创建时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
@TableField(fill = FieldFill.INSERT)
private Date gmtCreate;
//更新时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
@TableField(fill = FieldFill.INSERT)
private Date gmtModified;
@TableField(exist = false)
private List<EduSubject> children = new ArrayList<>();
}
package com.czxy.zx.course.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* @author 桐叔
* @email [email protected]
*/
@Component
public class SubjectMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
// 创建时间
this.setFieldValByName("gmtCreate",new Date(), metaObject);
// 修改时间
this.setFieldValByName("gmtModified",new Date() , metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
// 修改时,填充的内容
this.setFieldValByName("gmtModified",new Date() , metaObject);
}
}
接口
package com.czxy.zx.course.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.czxy.zx.domain.EduSubject;
/**
* @author 桐叔
* @email [email protected]
*/
public interface EduSubjectService extends IService<EduSubject> {
/**
* 通过title查询
* @param title
* @return
*/
EduSubject findByTitle(String title);
}
实现类
package com.czxy.zx.course.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.czxy.zx.course.mapper.EduSubjectMapper;
import com.czxy.zx.course.service.EduSubjectService;
import com.czxy.zx.domain.EduSubject;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* @author 桐叔
* @email [email protected]
*/
@Service
@Transactional
public class EduSubjectServiceImpl extends ServiceImpl<EduSubjectMapper, EduSubject> implements EduSubjectService {
@Override
public EduSubject findByTitle(String title) {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq("title", title);
EduSubject eduSubject = baseMapper.selectOne(queryWrapper);
return eduSubject;
}
}
/**
* 文件上传
* @param file
* @return
*/
@PostMapping("/upload")
public BaseResult upload(MultipartFile file) {
try {
// 解析excel
EasyExcel.read(file.getInputStream(), UploadSubjectVo.class, eduSubjectListener).sheet(0).doRead();
return BaseResult.ok("上传成功");
} catch (IOException e) {
return BaseResult.error("上传失败");
}
}
package com.czxy.zx.course.upload;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
/**
* @author 桐叔
* @email [email protected]
*/
@Data
public class UploadSubjectVo {
@ExcelProperty("一级分类")
private String oneLevel;
@ExcelProperty("二级分类")
private String twoLevel;
}
package com.czxy.zx.course.upload;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.czxy.zx.course.service.EduSubjectService;
import com.czxy.zx.domain.EduSubject;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* @author 桐叔
* @email [email protected]
*/
@Component
public class EduSubjectListener extends AnalysisEventListener<UploadSubjectVo> {
@Resource
private EduSubjectService eduSubjectService;
@Override
public void invoke(UploadSubjectVo uploadSubjectVo, AnalysisContext analysisContext) {
// 1. 处理一级
// 1.1 查询一级
EduSubject oneSubject = eduSubjectService.findByTitle(uploadSubjectVo.getOneLevel());
// 1.2 保存一级
if(oneSubject == null) {
oneSubject = new EduSubject();
oneSubject.setTitle(uploadSubjectVo.getOneLevel());
oneSubject.setSort(0);
oneSubject.setParentId("0"); // 一级默认0
eduSubjectService.save(oneSubject);
}
// 2. 处理二级
// 2.1 查询二级
EduSubject twoSubject = eduSubjectService.findByTitle(uploadSubjectVo.getTwoLevel());
// 2.2 保存二级
if(twoSubject == null) {
twoSubject = new EduSubject();
twoSubject.setTitle(uploadSubjectVo.getTwoLevel());
twoSubject.setSort(0);
twoSubject.setParentId(oneSubject.getId()); //二级的父ID为一级的ID
eduSubjectService.save(twoSubject);
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}
Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。
功能 | 描述 |
---|---|
HSSFWorkBook | 提供读写Microsoft Excel格式档案的功能 |
XSSFWorkBook | 提供读写Microsoft Excel OOXML格式档案的功能 |
HWPF | 提供读写Microsoft Word格式档案的功能 |
HSLF | 提供读写Microsoft PowerPoint格式档案的功能 |
HDGF | 提供读写Microsoft Visio格式档案的功能 |
http://poi.apache.org/
创建项目:
修改pom
<dependencies>
<dependency>
<groupId>org.apache.poigroupId>
<artifactId>poiartifactId>
<version>3.9version>
dependency>
<dependency>
<groupId>org.apache.poigroupId>
<artifactId>poi-ooxmlartifactId>
<version>3.9version>
dependency>
<dependency>
<groupId>joda-timegroupId>
<artifactId>joda-timeartifactId>
<version>2.10.1version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
dependency>
dependencies>
package com.zx.poi;
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.joda.time.DateTime;
import org.junit.Test;
import java.io.FileOutputStream;
import java.io.IOException;
public class Excel03Test {
@Test
public void testWrite03() throws IOException {
// 创建新的Excel 工作簿
Workbook workbook = new HSSFWorkbook();
// 在Excel工作簿中建一工作表,其名为缺省值 Sheet0
//Sheet sheet = workbook.createSheet();
// 如要新建一名为"信息统计"的工作表,其语句为:
Sheet sheet = workbook.createSheet("信息统计");
// 创建行(row 1)
Row row1 = sheet.createRow(0);
// 创建单元格(col 1-1)
Cell cell11 = row1.createCell(0);
cell11.setCellValue("今日人数");
// 创建单元格(col 1-2)
Cell cell12 = row1.createCell(1);
cell12.setCellValue(666);
// 创建行(row 2)
Row row2 = sheet.createRow(1);
// 创建单元格(col 2-1)
Cell cell21 = row2.createCell(0);
cell21.setCellValue("统计时间");
//创建单元格(第三列)
Cell cell22 = row2.createCell(1);
String dateTime = new DateTime().toString("yyyy-MM-dd HH:mm:ss");
cell22.setCellValue(dateTime);
// 新建一输出文件流(注意:要先创建文件夹)
FileOutputStream out = new FileOutputStream("d://zx/a.xls");
// 把相应的Excel 工作簿存盘
workbook.write(out);
// 操作结束,关闭文件
out.close();
System.out.println("文件生成成功");
}
}
excel2007+ 文件扩展名为 xlsx
package com.zx.poi;
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 org.joda.time.DateTime;
import org.junit.Test;
import java.io.FileOutputStream;
import java.io.IOException;
public class Excel07Test {
@Test
public void testWrite07() throws IOException {
// 创建新的Excel 工作簿
Workbook workbook = new XSSFWorkbook();
// 在Excel工作簿中建一工作表,其名为缺省值 Sheet0
//Sheet sheet = workbook.createSheet();
// 如要新建一名为"信息统计"的工作表,其语句为:
Sheet sheet = workbook.createSheet("信息统计");
// 创建行(row 1)
Row row1 = sheet.createRow(0);
// 创建单元格(col 1-1)
Cell cell11 = row1.createCell(0);
cell11.setCellValue("今日人数");
// 创建单元格(col 1-2)
Cell cell12 = row1.createCell(1);
cell12.setCellValue(666);
// 创建行(row 2)
Row row2 = sheet.createRow(1);
// 创建单元格(col 2-1)
Cell cell21 = row2.createCell(0);
cell21.setCellValue("统计时间");
//创建单元格(第三列)
Cell cell22 = row2.createCell(1);
String dateTime = new DateTime().toString("yyyy-MM-dd HH:mm:ss");
cell22.setCellValue(dateTime);
// 新建一输出文件流(注意:要先创建文件夹)
FileOutputStream out = new FileOutputStream("d://zx/b.xlsx");
// 把相应的Excel 工作簿存盘
workbook.write(out);
// 操作结束,关闭文件
out.close();
System.out.println("文件生成成功");
}
}
@Test
public void testRead03() throws Exception{
// 1 创建文件流
FileInputStream inputStream = new FileInputStream("d://zx//a.xls");
//2 根据流创建工作簿
Workbook workbook = new HSSFWorkbook(inputStream);
//3 获取sheet
Sheet sheet = workbook.getSheet("上课人数统计");
for(int i=0;i<5;i++){
//4 获取行
Row row = sheet.getRow(i);
//5 获取列中内容
//获取第一列
Cell nameCell = row.getCell(0);
String name = nameCell.getStringCellValue();
// 获取第二列
Cell sexCell = row.getCell(1);
String sex = sexCell.getStringCellValue();
//获取第三列
Cell ageCell = row.getCell(2);
String age = ageCell.getStringCellValue();
System.out.println(name+"\t\t\t"+sex+"\t\t\t"+age);
//\t 占8个字节的位置
// abc\t 'abc '
//abcdefgh\t 'abcdefgh'
//abcdefgh\t\t 'abcdefgh '
}
//6 关闭流
inputStream.close();
}
@Test
public void testRead07() throws Exception{
InputStream is = new FileInputStream("d:/zx/b.xlsx");
Workbook workbook = new XSSFWorkbook(is);
Sheet sheet = workbook.getSheetAt(0);
// 读取第一行第一列
Row row = sheet.getRow(0);
Cell cell = row.getCell(0);
// 输出单元内容
System.out.println(cell.getStringCellValue());
// 操作结束,关闭文件
is.close();
}
@Test
public void testRead07() throws Exception{
InputStream is = new FileInputStream("d:/0704.xlsx");
Workbook workbook = new XSSFWorkbook(is);
Sheet sheet = workbook.getSheetAt(0);
// 读取第一行第一列
Row row = sheet.getRow(0);
Cell cell1 = row.getCell(0);
Cell cell2 = row.getCell(1);
// 输出单元内容
System.out.println(cell1.getStringCellValue());
System.out.println(cell2.getNumericCellValue());
// 操作结束,关闭文件
is.close();
}