导入:将文档中数据导入到内存中,后续可以添加到数据库
导出:将内存中的数据或数据库中查询的数据导出到文档中
注意:这里指的文档通常指的是基本的办公软件:word,excel,ppt
绝大多数公司都在使用word和excel,如果我们开发的系统支持导入导出,我们开发的软件就相对会有优势
1.业务场景
案例1:
公司举行会议时的签到表
由系统运营人员将公司所有在职员工的信息导出为excel
由公司后勤或行政人员对excel表进行修改,然后打印进行签到
腾讯会议签到导出
案例2:
采购清单
后勤人员录入信息到excel
系统维护人员将excel导入到数据库
业务员线下推广收集用户数据,后面集中批量添加到数据库
2. Java操作办公软件
在开发中,我们经常需要写程序操作办公软件【其中操作得最多的就是Word与Excel】!因此我们使用代码生成,读取这些文件的数据也是很重要的一个功能
Java中提供了相应的操作办公软件的框架,其中,最常用的是下面两种:
jxl:只能对Excel进行操作,属于比较老的框架。
POI:是apache的项目,可对ms的word,Excel,PPT进行操作,包括office2003和2007。对两种版本的处理都比较好。具体操作请看官方的文档
3. POI的使用
咱们这里直接学习poi的使用,poi针对offices03(xls)与07(xlsx)是单独写了相应的实现api,我们这里直接使用07版的处理方案(注:网上是有相应的兼容方案,可判断)
4. EasyPOI导出数据
为了提高开发效率,我们这里使用easyPOI进行数据的导入导出
easypoi导入/导出excel其实就是domain对象属性和excel列的映射,而easypoi是通过注解的方式来做映射的,我们学习easypoi其实就是学会使用工具类和掌握它的常用注解
常见的注解有:
@Excel 作用到filed上面,是对Excel一列的一个描述
@ExcelCollection 表示一个集合,主要针对一对多的导出,比如一个老师对应多个科目,科目就可以用集合表示
@ExcelEntity 表示一个继续深入导出的实体,但他没有太多的实际意义,只是告诉系统这个对象里面同样有导出的字段
@ExcelIgnore 和名字一样表示这个字段被忽略跳过这个导导出
@ExcelTarget 这个是作用于最外层的对象,描述这个对象的id,以便支持一个对象可以针对不同导出做出不同处理
注意:hutools中也有导入导出的工具类,用法不太一样
4.1引入pom依赖
<!--poi依赖(生成Excel时需要用到此依赖包)-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
4.2. 添加工具类
package com.zt.basic.config;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
/**
* Excel导入导出工具类
* @author hm
*/
public class ExcelUtils{
/**
* 导出工具类
* @param list
* @param title
* @param sheetName
* @param pojoClass
* @param fileName
* @param isCreateHeader
* @param response
*/
public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass,
String fileName, boolean isCreateHeader, HttpServletResponse response){
ExportParams exportParams = new ExportParams(title, sheetName);
exportParams.setCreateHeadRows(isCreateHeader);
defaultExport(list, pojoClass, fileName, response, exportParams);
}
/**
* 导出工具类
* @param list
* @param title
* @param sheetName
* @param pojoClass
* @param fileName
* @param response
*/
public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass,String fileName,
HttpServletResponse response){
defaultExport(list, pojoClass, fileName, response, new ExportParams(title, sheetName));
}
public static void exportExcel(List<Map<String, Object>> list, String fileName, HttpServletResponse response){
defaultExport(list, fileName, response);
}
private static void defaultExport(List<?> list, Class<?> pojoClass, String fileName,
HttpServletResponse response, ExportParams exportParams) {
Workbook workbook = ExcelExportUtil.exportExcel(exportParams,pojoClass,list);
if (workbook != null); downLoadExcel(fileName, response, workbook);
}
private static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) {
try {
response.setCharacterEncoding("UTF-8");
response.setHeader("content-Type", "application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
workbook.write(response.getOutputStream());
} catch (IOException e) {
//throw new NormalException(e.getMessage());
}
}
private static void defaultExport(List<Map<String, Object>> list, String fileName, HttpServletResponse response) {
Workbook workbook = ExcelExportUtil.exportExcel(list, ExcelType.HSSF);
if (workbook != null);
downLoadExcel(fileName, response, workbook);
}
public static <T> List<T> importExcel(String filePath,Integer titleRows,Integer headerRows, Class<T> pojoClass){
if (StringUtils.isBlank(filePath)){
return null;
}
ImportParams params = new ImportParams();
params.setTitleRows(titleRows);
params.setHeadRows(headerRows);
List<T> list = null;
try {
list = ExcelImportUtil.importExcel(new File(filePath), pojoClass, params);
}catch (NoSuchElementException e){
//throw new NormalException("模板不能为空");
} catch (Exception e) {
e.printStackTrace();
//throw new NormalException(e.getMessage());
} return list;
}
public static <T> List<T> importExcel(MultipartFile file, Integer titleRows, Integer headerRows, Class<T> pojoClass){
if (file == null){ return null;
}
ImportParams params = new ImportParams();
params.setTitleRows(titleRows);
params.setHeadRows(headerRows);
List<T> list = null;
try {
list = ExcelImportUtil.importExcel(file.getInputStream(), pojoClass, params);
}catch (NoSuchElementException e){
// throw new NormalException("excel文件不能为空");
} catch (Exception e) {
//throw new NormalException(e.getMessage());
System.out.println(e.getMessage());
}
return list;
}
}
4.3 需求:前端请求导出
点击导出,导出前端按钮(作者用到的前端技术栈是vue)
导出按钮:
<el-form-item>
<!-- 默认name="file" -->
<el-upload class="upload-demo"
action="http://localhost:8080/shop/importExcel"
list-type="text">
<el-button type="warning">点击导入</el-button>
</el-upload>
</el-form-item>
导出方法:
// 导出方法
exportData(){
//this.$router.push({ path: '/register' });
location.href="http://localhost:8080/shop/export";
}
4.4 后端接口
/**
* 导出
* @param
* @return
*/
@GetMapping("/export")
public void export(HttpServletResponse response) {
List<Shop> shops = shopService.findAll();
ExcelUtils.exportExcel(shops, "店铺信息", "店铺数据", Shop.class, "店铺信息.xlsx", true, response);
}
4.5 domain层加注解
package com.zt.org.domain;
import cn.afterturn.easypoi.excel.annotation.Excel;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.zt.basic.domain.BaseDomain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Shop extends BaseDomain {
@Excel(name = "店铺名称",orderNum = "1",width = 30)
@NotNull(message = "店铺名字不能为空")
private String name;
@Excel(name = "店铺电话",orderNum = "2",width = 30)
@NotNull(message = "店铺电话不能为空")
private String tel;
@Excel(name = "店铺入驻时间", orderNum = "3", width = 50, format = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
private Date registerTime = new Date();
@Excel(name = "店铺状态", orderNum = "4", width = 30, replace = {"待审核_1", "待激活_2","已激活_3","驳回_4"})
private Integer state;
@Excel(name = "店铺地址", orderNum = "5", width = 50)
private String address;
private String logo;
private Long adminId;
@Valid
private Employee admin;
}
5. EasyPOI导入数据
5.1. 前端代码准备
对于excel导入,其实就是上传文件并解析内容,将excel里面的每一行数据解析为一个Shop对象再保存数据就行
<el-form-item>
<!-- 默认name="file" -->
<el-upload class="upload-demo"
action="http://localhost:8080/shop/importExcel"
list-type="text">
<el-button type="warning">点击导入</el-button>
</el-upload>
</el-form-item>
5.2 后端接口代码
/**
* 导入
* */
@PostMapping("/importExcel")
public void importExcel(@RequestPart MultipartFile file) {
// titleRows:占用了多少行
List<Shop> shops = ExcelUtils.importExcel(file, 1, 1, Shop.class);
shopService.batchAdd(shops);
}
注意:导入时需要注意格式