(1)java可以操作办公软件:
Word、Excel、PPT。其中Word和Excel操作最为频繁
(2)java操作Exccel
导入(磁盘数据读取到内存)导出
(3)java操作办公软件的框架
JXL:只操作Exccel,只支持office2003之前的,功能还是很强大的
POI:apatch公司的 ,支持word、Excel、ppt。它写了两套API,支持office2003及以前和office2007以后的,功能也很强大
找到POI的文档。以下使用office2007版本的(注:网上有相应的兼容方案,可判断)
HSSF(xls)是2003版本的
XSSF(xlsx)是2007版本的
(1)使用POI的前提,导入POI的相应的jar包
org.apache.poi
poi
3.11
org.apache.poi
poi-ooxml
3.11
(2)POI的导出。使用POI创建一个Excel的九九乘法表
//创建Excel表--poi的导出
@Test
public void myTestCreatExccel() throws Exception{
//1.创建一个Excel表(在内存中)
SXSSFWorkbook workbook = new SXSSFWorkbook();
//2.再创建一张sheet表(Excel表下方有表sheet1、sheet2、....)
Sheet sheet = workbook.createSheet("九九乘法表");
//3.创建行
for (int i=1;i<=9;i++){
Row row = sheet.createRow(i - 1);//减去1,最边上的行不要有空的
//4.创建列(格子)
for (int j=1;j<=i;j++){
Cell cell = row.createCell(j - 1);//减去1,最边上的列不要有空的
//5.往格子中加数据
cell.setCellValue(i+"*"+j+"="+(i*j));
}
}
//6.写到内存中去
FileOutputStream out = new FileOutputStream("template/99.xlsx");
workbook.write(out);
out.close();
workbook.dispose();
}
(3)POI的导入。读取数据到内存中来
//POI的导入--读取数据
@Test
public void myTestReadExcel() throws Exception{
//1.把数据template文件路径下的emp-poi.xlsx文件读取到内存中
Workbook workbook = WorkbookFactory.create(new File("template/emp-poi.xlsx"));
//2.根据文件拿到对应的表--此处是根据下标获取
Sheet sheet = workbook.getSheetAt(0);
//3.拿到表的对应的所有行
//LastRowNum:最后一行(总行数)
int lastRowNum = sheet.getLastRowNum();
//遍历所有行
for(int i = 1; i <= lastRowNum; i++) {
//拿到对应的行
Row row = sheet.getRow(i);
//4.拿到行对应的列(格子)
//lastCellNum:最后一列(总列数)
short cellNum = row.getLastCellNum();
//遍历总列数
for (int j = 0; j < cellNum; j++) {
//5.拿到格子中的数据
Cell cell = row.getCell(j);
//获取不到文件中的int类型数据。--解决;在文件中的int类型打个‘ 转成string类型--很low
System.out.print(cell.getStringCellValue() + " ");
}
System.out.println();
}
}
原生的POI操作还是比较复杂,所以基于POI又做了一层封装,使操作更加简单。springmvc支持
EasyPOI的网上文档路径:http://easypoi.mydoc.io/
在maven中引入easyPOI
(1)先导入EasyPOI的jar包。
注意;要把之前引入的POI的jar包去掉,否则会有冲突
cn.afterturn
easypoi-base
3.2.0
cn.afterturn
easypoi-web
3.2.0
cn.afterturn
easypoi-annotation
3.2.0
(2)测试一下EasyPOI导出
使用Excel注解版导入导出
先写一个domain类,在要导出到Excel的字段上打上@Excel注解
@Excel(name=“xx”,其他属性) 具体看文档,表示表头的信息
注意:
/*
* EasyPOI的准备类
* */
import cn.afterturn.easypoi.excel.annotation.Excel;
public class POIEmployee {
@Excel(name = "编号")
private Long id;
//姓名
@Excel(name = "用户名")//表头的名字
private String username;
//邮件
@Excel(name = "邮箱",width = 20)//还可以扩展表格宽度
private String email;
//以下省略了get/set方法和tostring方法
测试类
/*
* EasyPOI的测试类
* */
public class EasyPOITest {
@Test
public void myTest() throws Exception{
//1.模拟数据库中的数据
POIEmployee e1 = new POIEmployee();
e1.setId(1L);
e1.setUsername("张三");
e1.setEmail("[email protected]");
POIEmployee e2 = new POIEmployee();
e2.setId(2L);
e2.setUsername("李四狗");
e2.setEmail("[email protected]");
//2.将数据放到集合中去
List list=new ArrayList<>();
list.add(e1);
list.add(e2);
//3.将拿到的数据写到Excel中去,然后生成Excel
/*
* 以下都是从文档中拷贝的,但是要理解方法的用法,参数的意思
* exportExcel:导出
* ExcelExportUtil.exportExcel:导出一个excel
* new ExportParams("表头","二级表头","表名") 也可以不用设置,默认Excel中的
* POIEmployee.class:引出的类是谁
* list:导出的数据
* */
//--------------拷贝过来稍微更改一部分就可用(类型、数据、表名、表头....)--------------------------
Workbook wb = ExcelExportUtil.exportExcel(new ExportParams("员工数据","员工表"),
POIEmployee.class, list);
//-----------------------写死部分,直接拿来用---------------------------
//4.将数据写到Excel文件中去--拿到输出流,会自动在template下创建个poiemp.xlsx文件
FileOutputStream fileOutputStream = new FileOutputStream("template/poiemp.xlsx");
//写到文件中去
wb.write(fileOutputStream);
//关闭流
fileOutputStream.close();
}
}
(3)以上是简单的string类型的配置,那其他配置怎么使用呢?
布尔类型配置显示性别,在上面实体类代码的基础上增加一个性别的布尔字段。在性别的注解@Excel中写个replace={“男_true”,“女_false”}—>true代表男,false代表女。也可以用int类型1、2表示,用法都是一样的
日期的格式化展示问题。format = “yyyy-MM-dd”:日期的格式 ,注意:如果数据库是varchar,还需要配置databaseFormat。
图片的导出。添加属性type = 2 :代表该字段类型为图片。默认的是type=1,不展示图片
实体类字段的注解@Excel配置
@Excel(name = "编号")
private Long id;
//姓名
@Excel(name = "用户名")//表头的名字
private String username;
//邮件
@Excel(name = "邮箱",width = 20)//还可以扩展表格宽度
private String email;
//性别 true:男 false:女
@Excel(name="性别", replace={"男_true","女_false"})
private Boolean sex=true;
//入职日期
@Excel(name = "入职日期",format="yyyy-MM-dd")
private Date bornDate = new Date();
//头像图片
@Excel(name = "头像",type = 2,height = 20,width = 20)
private String headImage;
//省略get/set方法
在模拟数据库的测试中
/*
* EasyPOI的测试类
* */
public class EasyPOITest {
@Test
public void myTest() throws Exception{
//1.模拟数据库中的数据
POIEmployee e1 = new POIEmployee();
e1.setId(1L);
e1.setUsername("张三");
e1.setEmail("[email protected]");
e1.setSex(true);
e1.setHeadImage("22.jpg");
POIEmployee e2 = new POIEmployee();
e2.setId(2L);
e2.setUsername("李四狗");
e2.setEmail("[email protected]");
e2.setSex(false);
e2.setHeadImage("44.jpg");
//2.将数据放到集合中去
List list=new ArrayList<>();
list.add(e1);
list.add(e2);
//3.将拿到的数据写到Excel中去,然后生成Excel
/*
* 以下都是从文档中拷贝的,但是要理解方法的用法,参数的意思
* exportExcel:导出
* ExcelExportUtil.exportExcel:导出一个excel
* new ExportParams("表头","二级表头","表名") 也可以不用设置,默认Excel中的
* POIEmployee.class:引出的类是谁
* list:导出的数据
* */
//稍微更改一部分代码。类型、数据、表名、表头....
Workbook wb = ExcelExportUtil.exportExcel(new ExportParams("员工数据","员工表"),
POIEmployee.class, list);
//写死部分,以后要用直接拷贝过去用
//4.将数据写到Excel文件中去--拿到输出流,会自动在template下创建个poiemp.xlsx文件
FileOutputStream fileOutputStream = new FileOutputStream("template/poiemp.xlsx");
//写到文件中去
wb.write(fileOutputStream);
//关闭流
fileOutputStream.close();
}
}
重要的配置:
public class POIDepartment {
//部门id
private Long id;
//部门名称
@Excel(name = "部门名称")
private String name;
//部门地址
@Excel(name = "部门地址")
private String address="东北路2号";
//省略get/set方法
在员工实体类中添加个部门的字段,并注解@ExcelEntity标记导出Excel部门为实体类
//部门
@ExcelEntity//标记导出Excel的部门为实体类
private POIDepartment department;
//省略get/set方法
最后的效果展示图
需求:
既然两个实体类可以产生关联。我要在员工Excel表中部门的显示为:部门名称和部门地址。在部门Excel表中显示为:名称和地址,怎么办?
在类上使用@ExcelTarget注解:限制一个实体的注解,官方文档上有解释。
在员工实体类POIEmployee上打上@ExcelTarget注解
//员工实体类
@ExcelTarget("emp")
public class POIEmployee {
//省略
}
还要在部门实体类上打上一样的注解
//部门实体类
@ExcelTarget("dept")
public class POIDepartment {
//省略
}
然后部门实体类上相关联的字段上的注解@Excel(name=“xx”)稍微的改动
//部门名称
@Excel(name = "部门名称_emp,名称_dept")
private String name;
//部门地址
@Excel(name = "部门地址_emp,地址_dept")//在emp员工Excel表中是部门地址,在dept部门Excel表中是地址
private String address="东北路2号";
//省略get/set方法
展示的效果图
部门的Excel表:
员工的Excel表:
那如果不想让员工Excel表看到部门地址,部门Excel能看到部门地址 ,怎么操作?
只需要将部门实体类的部门地址字段改动下即可。
//部门地址
@Excel(name = "地址_dept")//在emp员工Excel表中不显示,在dept部门Excel表中显示地址
private String address="东北路2号";
总体归纳一下:
给员工实体类中的部门实体类字段打注解@ExcelEntity,那么部门实体类的字段上打了@Excel注解的字段都会显示在员工Excel表中。如果想要两张表某些字段在不同表中的显示不一样,那么就要给每个实体类上打上注解@ExcelTarget(“xx”),表示实体类的名称,然后在需要调整的字段上做相应的调整即可。比如@Excel(name = “部门名称_emp,名称_dept”):表示在emp员工Excel表中显示的是部门名称,而在dept部门的Excel表中显示的是名称。但是如果想要某个字段不要显示在其他Excel表中,只显示在自己的Excel表中,就将上面的注解改为@Excel(name = “地址_dept”) :表示员工Excel表不显示这个字段,部门Excel表显示为地址。
(4)测试下easypoi的导入
准备好了一个poiemp.xlsx文件,也是被读取的文件
//easypoi导入
@Test
public void myTestRead() throws Exception{
//设置导入的参数
ImportParams params = new ImportParams();
//准备的poiemp.xlsx文件,标题有一行(如果要读取的文件没有就不用设置)
params.setTitleRows(1);
//poiemp.xlsx文件,头也有一行(如果要读取的文件没有就不用设置)
params.setHeadRows(1);
/*
* 从文档中拷贝过来,稍微更改:
* 导入的类型,准备读取的文件,导入的参数
* */
List list = ExcelImportUtil.importExcel(
new File("template/poiemp.xlsx"),
POIEmployee.class, params);
//遍历文件中的数据集合,打印读取出来
for (POIEmployee employee : list) {
System.out.println(employee);
}
}
读取的下效果:
文件中的所有信息全部读取出来,并且注意看下图片导入到电脑中的路径。图片会自动保存到项目的那个盘符中的excel文件中去。可以去找到它
EasyPOI可以支持SpringMVC的
需求;要在员工页面新增一个导出功能。
导出的数据有:头像、用户名、邮件、年龄、部门
(1)由于EasyPOI可以支持SpringMVC,EasyPOI view项目是为了更简单的方便搭建在导出时候的操作,利用spring mvc的view封装,更加符合spring mvc的风格。
view下面包括多个 view的实现:
EasypoiBigExcelExportView 大数据量导出
EasypoiMapExcelView map 列表导出
EasypoiPDFTemplateView pdf导出
EasypoiSingleExcelView 注解导出
EasypoiTemplateExcelView 模板导出
EasypoiTemplateWordView word模板导出
MapGraphExcelView 图表导出
注意:
注解目录扫描的时候加上cn.afterturn.easypoi.view就可以使用了,让springmvc知道有这个Excel的view包。
(2)先在domain层的Employee类中的上述字段打上@Excel注解,注意还要在部门字段上打注解@ExcelEntity:easypoi标记导出Excel部门为实体类,这个 千万不能忘记。与部门domain类建立关联,与此同时还要 在部门domain类Department中的name字段上打上@Excel(name=“部门名称”)注解。
Employee.java部分
//头像
@Excel(name = "头像",type = 2,height = 30)
private String headImage;
//用户名
@Excel(name = "用户名")
private String username;
//邮件
@Excel(name = "邮件",width = 25)
private String email;
//年龄
@Excel(name = "年龄")
private Integer age;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "department_id")
@ExcelEntity//easypoi标记导出Excel部门为实体类
private Department department;
//省略get/set方法
Department.java部分
@Excel(name = "部门名称")
private String name;
//省略get/set方法
(3)准备一个到导出按钮
在员工页面Employee.jsp中设置一个按钮
导出
(4)在员工controller层EmployeeController写导出的路径代码
//导出按钮方法
@RequestMapping("/export")
public String export(ModelMap map){
//从数据库中拿出到数据
List list = iEmployeeService.findAll();
//如何从数据库中拿出到数据变成Excel中的数据,并且导出到前台
ExportParams params = new ExportParams("员工管理", "员工表", ExcelType.XSSF);
// params.setFreezeCol(2);//冻结
map.put(NormalExcelConstants.DATA_LIST, list); // 数据集合(导出的数据)
map.put(NormalExcelConstants.CLASS, Employee.class);//导出实体
map.put(NormalExcelConstants.PARAMS, params);//参数
map.put(NormalExcelConstants.FILE_NAME, "员工表");//文件名称
//return "easypoiExcelView"; /WEB-INF/views/easypoiExcelView.jsp
return NormalExcelConstants.EASYPOI_EXCEL_VIEW;//View名称
}
点击时报错:
分析:
返回的 easypoiExcelView源码:
controller层最后返回到这里,进行进一步的导出操作
(5)解决上述问题
在applicationContext-mvc.xml中配置扫描Excel的view包
注意事项:
在applicationContext-mvc.xml中有个视图解析器,在扫描Excel的view包的时候会经过这个视图解析器,然后路径就会是这样的:/WEB-INF/views/easypoiExcelView.jsp,相当于扫描Excel的view包就被视图解析器给拦截了。
解决上述问题:
配置个bean的视图解析器 ,并且优先级在最前面,配置伪属性p:order=“0”:顺序在最前面,告诉springmvc先找配置的bean的视图解析器,也就是找到自己的源码easypoiExcelView,如果找不到再去找原来的视图解析器。
详解伪属性p:order=“0”:等同于这样写
伪属性的 p:order=“0”
最后效果
再来解决头像图片问题
分析:可能是路径问题造成的,所以告诉它图片的路径在哪即可。
拿到真实路径realpath
//导出按钮方法
@RequestMapping("/export")
public String export(ModelMap map, HttpServletRequest request){
//从数据库中拿出员工数据
List list = iEmployeeService.findAll();
//----------------------------------------------------------------
//解决员工头像问题。拿到真实路径
String realPath = request.getServletContext().getRealPath("");
System.out.println(realPath);//H:\IDEA\idea_workspace\aisell\target\ssj
//遍历拿到的数据集合
list.forEach(e->{
//拼接处图片的路径
e.setHeadImage(realPath+e.getHeadImage());
});
//----------------------------------------------------------------
//如何从数据库中拿出到数据变成Excel中的数据,并且导出到前台
ExportParams params = new ExportParams("员工管理", "员工表", ExcelType.XSSF);
// params.setFreezeCol(2);//冻结
map.put(NormalExcelConstants.DATA_LIST, list); // 数据集合(导出的数据)
map.put(NormalExcelConstants.CLASS, Employee.class);//导出实体
map.put(NormalExcelConstants.PARAMS, params);//参数
map.put(NormalExcelConstants.FILE_NAME, "员工表");//文件名称
//return "easypoiExcelView"; /WEB-INF/views/easypoiExcelView.jsp
return NormalExcelConstants.EASYPOI_EXCEL_VIEW;//View名称
}
}
功能需求:导出与高级查询结合,想要什么数据就导出想要的数据
在Employee.jsp中:
更改一下导出的提交方式:
form表单为post方法提交,并且给出action="/employee/export"的路径。
导出用按钮,不写type,默认就是submit提交方式。然后将form表单提交到后台。这样查询用的是a标签,并且执行的是查询方法,就不影响到导出功能
在后台EmployeeController中
既然是高级查询,那么就要拿到查询对象query,然后根据条件到后台去查询数据再执行导出方法
操作效果图:
(1)准备一张要导入的Excel表。
注意:Excel表中的字段名称要跟domain类中打的注解@Excel(name=“名称”)一致,才能成功。
(2)新建一个导入的jsp页面import.jsp
根据视图解析器;在webapp/WEB-INF/views/import.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
<%@include file="/WEB-INF/views/head.jsp" %>
(3)controller层准备ImportController
第一:密码问题,Excel表中没有密码。给它个初始密码
第二:JPA的瞬时状态。由于表中有部门,但是没有部门的id,你保存员工时就有部门,但是没有部门id,部门的主键是空的。
解决办法:
根据对象拿到部门。
在DepartmentRepository
//根据用户名拿到部门
Department findByName(String name);
在IDepartmentService
//根据用户名拿到部门
Department findByName(String name);
在DepartmentServiceImpl
@Service
public class DepartmentServiceImpl extends BaseServiceImpl implements IDepartmentService {
@Autowired
private DepartmentRepository departmentRepository;
@Override
public Department findByName(String name) {
return departmentRepository.findByName(name);
}
}
ImportController层
/*
* easypoi导入的controller
* */
@Controller
@RequestMapping("/import")
public class ImportController {
//注入IEmployeeService对象
@Autowired
private IEmployeeService employeeService;
//注入IDepartmentService部门对象
@Autowired
private IDepartmentService departmentService;
@RequestMapping("/index")
public String index(){
return "import";
}
//上传员工的Excel操作
@RequestMapping("/employeeXlsx")
public String employeeXlsx(MultipartFile empFile) throws Exception{
//设置导入的参数
ImportParams params = new ImportParams();
//params.setTitleRows(1);//导入的Excel表没有标题头
params.setHeadRows(1);
List list = ExcelImportUtil.importExcel(
//使用importExcel的流的参数
empFile.getInputStream(),
Employee.class, params);
list.forEach(e-> {
// System.out.println(e+","+e.getDepartment());
//从数据库中查询部门--解决JPA的瞬时异常问题。Excel表中的部门没有id,只有部门名称。所以保持的是部门主键是空的
String deptName = e.getDepartment().getName();
System.out.println("-----"+deptName);
//在根据部门名称去数据库查部门(数据库中的部门就有id值)
Department dept = departmentService.findByName(deptName);
e.setDepartment(dept);
//设置初始密码--解决Excel表中没有密码字段的问题
e.setPassword("123");
//保持到数据库中
employeeService.save(e);
System.out.println("====="+e);
});
//导入成功后返回原页面
return "import";
}
}
准备的导入的一张表要满足一定的规则才能导入到数据库中,比如:名字和数据库中的名字不能为空、重复之类的 ,年龄不能大于多少或者小于多少等等验证,将导入失败的数据单独下载到Excel表中,并在每行失败数据后面注明导入失败原因。
(1)理解:Excel导入校验
校验,是一个不可或缺的功能,现在java校验主要是JSR 303 规范,实现方式主流的有两种
Hibernate Validator和Apache Commons Validator。
(2)导入JSR 303 规范的验证jar包
org.hibernate
hibernate-validator
5.2.4.Final
(2)在相应的字段上加上注解
(3)准备一个自定义的验证规则类
/*
* 导入Excel文件的自定义验证规则
* Excel表中的用户名不能和数据库中已有的用户名重复
* 自定义的验证规则类要实现IExcelVerifyHandler接口类
* 要让spring生成bean,加上注解@Component(其他层就用这个注解)
* */
@Component//告诉spring这里要生成bean
public class EmployeeExcelVerifyHandler implements IExcelVerifyHandler {
//注入IEmployeeService对象,才能在下面和数据库中的用户名进行验证
@Autowired
private IEmployeeService employeeService;
@Override
public ExcelVerifyHandlerResult verifyHandler(Employee employee) {
//写逻辑验证用户名是否重复。直接调用之前写法的验证登录注册用户名是否重复的方法checkName
boolean success = employeeService.checkName(employee.getUsername());
if(success){ //true代表可以用
//ExcelVerifyHandlerResult类:只有布尔类型的success字段和string类型的msg字段。看源码
return new ExcelVerifyHandlerResult(true);
}
return new ExcelVerifyHandlerResult(false,"用户名重复");
}
}
(4)还要告诉ImportController,要在里面进行Excel导入的自定义的验证。
通过sprig注入自定义验证的bean对象
(5)核心代码:ImportController部分
/*
* easypoi导入的controller
* */
@Controller
@RequestMapping("/import")
public class ImportController {
//注入IEmployeeService对象
@Autowired
private IEmployeeService employeeService;
//注入IDepartmentService部门对象
@Autowired
private IDepartmentService departmentService;
//注入Excel导入的自定义验证的对象
@Autowired
private EmployeeExcelVerifyHandler employeeExcelVerifyHandler;
@RequestMapping("/index")
public String index(){
return "import";
}
//上传员工的Excel操作--具有Excel导入验证功能
@RequestMapping("/employeeXlsx")
public String employeeXlsx(MultipartFile empFile) throws Exception{
//设置导入的参数
ImportParams params = new ImportParams();
//params.setTitleRows(1);//导入的Excel表没有标题头
//代表这里是需要验证
params.setNeedVerfiy(true);
params.setHeadRows(1);
//加入自定义验证。告诉controller这里要进行自定义的验证
params.setVerifyHandler(employeeExcelVerifyHandler);
ExcelImportResult result = ExcelImportUtil.importExcelMore(
//使用importExcel的流的参数
empFile.getInputStream(),
Employee.class, params);
//拿到正确数据
List list = result.getList();
list.forEach(e->{
System.out.println("正确的"+e);
});
//拿到错误数据
List failList = result.getFailList();
failList.forEach(e->{
System.out.println("错误的"+e);
});
(6)测试一下效果:
Excel表:admin数据库中已存在、第二个用户名为空、第四个年龄大于80岁
打印结果:
需求:要将不符合的数据单独导出到一个Excel表中,并且后面给出失败的原因,合格的数据就直接添加到数据库中去。
/*
* easypoi导入的controller
* */
@Controller
@RequestMapping("/import")
public class ImportController {
//注入IEmployeeService对象
@Autowired
private IEmployeeService employeeService;
//注入IDepartmentService部门对象
@Autowired
private IDepartmentService departmentService;
//注入Excel导入的自定义验证的对象
@Autowired
private EmployeeExcelVerifyHandler employeeExcelVerifyHandler;
@RequestMapping("/index")
public String index(){
return "import";
}
//上传员工的Excel操作--具有Excel导入验证功能
@RequestMapping("/employeeXlsx")
public String employeeXlsx(MultipartFile empFile, HttpServletResponse response) throws Exception{
//设置导入的参数
ImportParams params = new ImportParams();
//params.setTitleRows(1);//导入的Excel表没有标题头
//代表这里是需要验证
params.setNeedVerfiy(true);
params.setHeadRows(1);
//加入自定义验证。告诉controller这里要进行自定义的验证
params.setVerifyHandler(employeeExcelVerifyHandler);
ExcelImportResult result = ExcelImportUtil.importExcelMore(
//使用importExcel的流的参数
empFile.getInputStream(),
Employee.class, params);
//拿到正确数据,然后将正确的数据保存到数据库中去
List list = result.getList();
list.forEach(e-> {
//从数据库中查询部门--解决JPA的瞬时异常问题。Excel表中的部门没有id,只有部门名称。所以保持的是部门主键是空的
String deptName = e.getDepartment().getName();
//在根据部门名称去数据库查部门(数据库中的部门就有id值)
Department dept = departmentService.findByName(deptName);
e.setDepartment(dept);
//设置初始密码--解决Excel表中没有密码字段的问题
e.setPassword("123");
//保持到数据库中
employeeService.save(e);
});
//创建一个错误数据的Excel表
Workbook failWorkbook = result.getFailWorkbook();
//用下载功能把文件写出去(下载;把文件变成一个流并写出去,还要设置响应头,所以要用到响应对象)
//下面设置好直接使用即可导出
//设置响应的文件类型 mime类型
//application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:指的是Excel2007版
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
//attachment:不要用浏览器打开(这是下载)
response.setHeader("Content-disposition", "attachment;filename=empFail.xlsx");
response.setHeader("Pragma", "No-cache");//设置不要缓存
//拿到输出流
OutputStream ouputStream = response.getOutputStream();
//将错误信息写出去
failWorkbook.write(ouputStream);
//刷新流
ouputStream.flush();
//关闭流
ouputStream.close();
//导入成功后返回原页面
return "import";
}
}
掌握这个很重要,java经常操作办公软件,这个就很实用