easypoi功能如同名字easy,主打的功能就是容易,让一个没见接触过poi的人员
就可以方便的写出Excel导出,Excel模板导出,Excel导入,Word模板导出,通过简单的注解和模板
语言(熟悉的表达式语法),完成以前复杂的写法
**
这个服务即将关闭,文档迁移到 http://www.wupaas.com/ 请大家访问最新网站
**
不如poi那么自定义,不如jxl那么多标签,但是我们就是写的少,写的少
EasyPoi的主要特点
1.设计精巧,使用简单
2.接口丰富,扩展简单
3.默认值多,write less do more
4.spring mvc支持,web导出可以简单明了
功能
Excel自适应xls和xlsx两种格式,word只支持docx模式
1.Excel导入
注解导入
Map导入
大数据量导入sax模式
导入文件保存
文件校验
字段校验
2.Excel导出
注解导出
模板导出
html导出
3.Excel转html
4.word导出
5.pdf导出
1.2 Easypoi介绍
Easypoi 为谁而开发
不太熟悉poi的
不想写太多重复太多的
只是简单的导入导出的
喜欢使用模板的
都可以使用easypoi
Easypoi的目标是什么
Easypoi的目标不是替代poi,而是让一个不懂导入导出的快速使用poi完成Excel和word的各种操作,而不是看很多api才可以完成这样工作
为什么会写Easypoi
以前的以前(岁月真TMD的快)我虽然写了不少代码但还是很少写poi,然后跳到一家公司之后就和业务人员聊上了,来这个需要个报表,这个报表样式是这样的,这个表头是这样的,就这样我写了大量的poi代码,每次都是大量的篇幅,copy to copy,无聊的一逼,然后加入了jeecg,jeecg中有一个小的工具类,虽然我也不知道是谁写的,然是可以用注解搞定最简单的导出,突然豁然开朗,我可以完善,让我从报表的苦海当中脱离出来,这样我花了一周的时间做了第一个版本支持导入导出放到了jeecg,发现还是不错的,慢慢的用的人越来越多,我就把这块独立出来了,再然后有人提出了模板,然后就加入了模板功能,提出了word的需求,加入了word的功能,后来工作忙了虽然没再参与jeecg,但还是一直维持这easypoi的更新,根据见识的增长也不断的重构这代码,直到现在
独特的功能
基于注解的导入导出,修改注解就可以修改Excel
支持常用的样式自定义
基于map可以灵活定义的表头字段
支持一堆多的导出,导入
支持模板的导出,一些常见的标签,自定义标签
支持HTML/Excel转换,如果模板还不能满足用户的变态需求,请用这个功能
支持word的导出,支持图片,Excel
小白如何开始
下载demo运行看看,基本上常见的用用法都在里面easypoi-test
查看几个*Util的用法,Easypoi的主要输出就是这个
看看注解的意思
看看模板的标签用法
可以出师了
- 可能存在的小坑
- 先写model
- 再写controller
- 最后写service
缓存问题
缓存问题好像是很多童鞋都遇到的问题,可能是我设计的逻辑问题,但是一直没有好的解决,
但是我也给了一个无奈的解决方案,大家可以自己实现接口IFileLoader
public interface IFileLoader {
/**
* 可以自定义KEY的作用
* @param key
* @return
*/
public byte[] getFile(String key);
}
来自己获取自己的文件,用来解决文件获取不到的问题
设置提供了两种方案,都是POICacheManager 的静态方法
public static void setFileLoder(IFileLoader fileLoder) {
POICacheManager.fileLoder = fileLoder;
}
/**
* 一次线程有效
* @param fileLoder
*/
public static void setFileLoderOnce(IFileLoader fileLoder) {
if (fileLoder != null) {
LOCAL_FILELOADER.set(fileLoder);
}
}
第一个是全局替换,可以在项目启动的时候,设置下就可以了,第一个是当前线程有效,希望可以帮助大家解决问题,我再研究下更通用的文件获取,或者那位朋友提供下自己的通用方案。
注解介绍
easypoi起因就是Excel的导入导出,最初的模板是实体和Excel的对应,model–row,filed–col 这样利用注解我们可以和容易做到excel到导入导出
经过一段时间发展,现在注解有5个类分别是
@Excel 作用到filed上面,是对Excel一列的一个描述
@ExcelCollection 表示一个集合,主要针对一对多的导出,比如一个老师对应多个科目,科目就可以用集合表示
@ExcelEntity 表示一个继续深入导出的实体,但他没有太多的实际意义,只是告诉系统这个对象里面同样有导出的字段
@ExcelIgnore 和名字一样表示这个字段被忽略跳过这个导导出
@ExcelTarget 这个是作用于最外层的对象,描述这个对象的id,以便支持一个对象可以针对不同导出做出不同处理
注解中的ID的用法
这个ID算是一个比较独特的例子,比如
@ExcelTarget(“teacherEntity”)
public class TeacherEntity implements java.io.Serializable {
/** name */
@Excel(name = “主讲老师_teacherEntity,代课老师_absent”, orderNum = “1”, mergeVertical = true,needMerge=true,isImportField = “true_major,true_absent”)
private String name;
这里的@ExcelTarget 表示使用teacherEntity这个对象是可以针对不同字段做不同处理
同样的ExcelEntity 和ExcelCollection 都支持这种方式
当导出这对象时,name这一列对应的是主讲老师,而不是代课老师还有很多字段都支持这种做法
@Excel
这个是必须使用的注解,如果需求简单只使用这一个注解也是可以的,涵盖了常用的Excel需求,需要大家熟悉这个功能,主要分为基础,图片处理,时间处理,合并处理几块,name_id是上面讲的id用法,这里就不累言了
在这之前先引入依赖
<!-- Excel导入导出-->
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>3.2.0</version>
</dependency>
</dependencies>
@Data
@Slf4j
@NoArgsConstructor
@AllArgsConstructor
public class MonthlyReportDTO extends BaseDTO {
/*type=> 导出类型 1 是文本 2 是图片,3 是函数,10 是数字 默认是文本*/
@Excel(name = "项目名称",orderNum="1" )
private String name;//项目名称
@Excel(name = "项目所属单位",orderNum="2" )
private String projectUnit;//项目所属单位
@Excel(name = "总投资",type = 10,orderNum="3" )
private Double totalnvestment;//总投资
@Excel(name = "年度计划",type = 10,orderNum="4" )
private Double yearPlan;//年度计划
@Excel(name = "本月投资完成",type = 10,orderNum="5" )
private Double theMonthInvestment;//本月投资完成
@Excel(name = "本年累计投资完成",type = 10,orderNum="6" )
private Double theYearTotalInvestment;//本年累计投资完成
@Excel(name = "自开工累计投资完成",type = 10,orderNum="7" )
private Double fromheadTotalInvestment;//自开工累计投资完成
@Excel(name = "年计划完成率(%)",type = 10,orderNum="8" )
private Double yearPlanCompletion;//年计划完成率(%)
@Excel(name = "形象进度",orderNum="9" )
private String imageProgress;//形象进度
@Excel(name = "形象进度百分比",type = 10,orderNum="10" )
private Integer imageProgressPercentage;//形象进度百分比
@Excel(name = "附件",orderNum="11")
private String file;//附件
@Excel(name = "上月本年累计",type = 10,orderNum="12" )
private Double lastMonthTheYearTotal;//上月本年累计
@Excel(name = "上月开工累计",type = 10,orderNum="13" )
private Double lastMonthstartsTotal;//上月开工累计
@Excel(name = "备注",orderNum="14" )
private String note;//备注
}
//你用哪个实体类装的数据就给谁加@Excel注解
@RestController
@Slf4j
@RequestMapping(value = "Url映射地址")
public class 类名 extends UpdateController<实体类, 实体类DTO> {
//Excel导入
@PostMapping(value = "Url映射地址")
public ResponseCode<String> excelImport(@RequestParam("file") MultipartFile file){
ResponseCode<String> responseCode = ResponseCode.sucess();
responseCode.setMsg(monthlyReportUpdateService.excelImport(file));
return responseCode;
}
}
@RestController
@Slf4j
@RequestMapping(value = "monthlyReport/query")
public class MonthlyReportQuaryController extends QueryController<实体, 实体DTO> {
//Excel导出
@GetMapping(value = "excel/export")
public void exportExcel(HttpServletResponse response){
monthlyReportService.exportExcel(response);
}
}
public interface MonthlyReportService extends QueryService<实体, 实体DTO> {
String exportExcel(HttpServletResponse response);//导出表格数据
}
public interface MonthlyReportUpdateService extends UpdateService<MonthlyReport, MonthlyReportDTO> {
String excelImport(MultipartFile file);//导入Excel
}
@Service
@Slf4j
public class MonthlyReportServiceImpl extends QueryServiceImpl<实体, 实体DTO> implements MonthlyReportService{
//导出
@Override
public String exportExcel(HttpServletResponse response) {
List<MonthlyReport> list = monthlyReportRespository.findAll();
System.out.println(list);
List<MonthlyReportDTO> dtoList=monthlyReportMapper.toMonthlyReportDTOList(list);
String msg="";
LocalDate localDate=LocalDate.now();
String s=""+localDate;
StringBuilder Month=new StringBuilder(s);
s=Month.substring(6,7);
try {
ExportParams params = new ExportParams("信息化项目"+s+"月投资完成情况月报", "测试", ExcelType.XSSF);
// Workbook workbook = ExcelExportUtil.exportExcel(params, MonthlyReportDTO.class, dtoList);
// msg="H:/ideaProject/InvestmentJava/InvestmentSystem/HandleSystem-CardDev/AdministratorService/src/main/resources/excelFile/信息化项目"+s+"月投资完成情况月报.xlsx";
// File file=new File(msg);
// if(!file.exists()){
// file.createNewFile();
// }else{
// file.delete();
// file.createNewFile();
// }
// FileOutputStream fos = new FileOutputStream(file);
// workbook.write(fos);
// System.out.println("导出成功");
// fos.close();
String fileName = "信息化项目"+s+"月投资完成情况月报.xlsx";
String sheetName = "月投资完成情况月报";
response.setHeader("content-Type", "application/vnd.ms-excel");
fileName = new String(fileName.getBytes(), "utf-8");
response.setHeader("Content-Disposition", "attachment;filename="+ new String( fileName.getBytes("gb2312"), "ISO8859-1" ) );
ServletOutputStream out = response.getOutputStream();
Workbook workbooks = ExcelExportUtil.exportExcel(params, MonthlyReportDTO.class, dtoList);
workbooks.write(out);
msg="2";
} catch (IOException e) {
e.printStackTrace();
}
return msg;
}
}
@Service
@Slf4j
public class MonthlyReportUpdateServiceImpl extends UpdateServiceImpl<MonthlyReport, MonthlyReportDTO> implements MonthlyReportUpdateService{
@Autowired
private MonthlyReportMapper monthlyReportMapper;
@Autowired
private MonthlyReportUpdateRespository monthlyReportUpdateRespository;
public MonthlyReportUpdateServiceImpl(MonthlyReportUpdateRespository monthlyReportUpdateRespository) {
super(monthlyReportUpdateRespository);
}
//excel导入
@Override
public String excelImport(MultipartFile file) {
int i=0;//成功条数
int j=0;//失败条数
String msg="";//返回信息
ImportParams params = new ImportParams();
params.setHeadRows(1);
params.setTitleRows(2);
params.setStartRows(1);
params.setNeedVerfiy(true);
try {
List<MonthlyReportDTO> list = ExcelImportUtil.importExcel(file.getInputStream(), MonthlyReportDTO.class, params);
//我也不知道为啥这上面导出来的数据中竟会有空数据的所以我就加了以下的判断
//也希望你们能测试一下如果知道问题了有了更好的解决方法hua'nign
for (MonthlyReportDTO l:list){
MonthlyReportDTO monthlyReportDTO =l;
if(monthlyReportDTO.getNote()!=null||
monthlyReportDTO.getLastMonthstartsTotal()!=null||
monthlyReportDTO.getLastMonthTheYearTotal()!=null||
monthlyReportDTO.getFile()!=null||
monthlyReportDTO.getImageProgressPercentage()!=null||
monthlyReportDTO.getImageProgress()!=null||
monthlyReportDTO.getYearPlanCompletion()!=null||
monthlyReportDTO.getFromheadTotalInvestment()!=null||
monthlyReportDTO.getTheYearTotalInvestment()!=null||
monthlyReportDTO.getTheMonthInvestment()!=null||
monthlyReportDTO.getYearPlan()!=null||
monthlyReportDTO.getTotalnvestment()!=null||
monthlyReportDTO.getProjectUnit()!=null||
monthlyReportDTO.getName()!=null) {
j++;
MonthlyReport m=monthlyReportMapper.toMonthlyReport(monthlyReportDTO);
monthlyReportUpdateRespository.save(m);
}else {
i++;
continue;
}
}
return "成功了"+j+"条";
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}