SpringBoot整合POI导出通用Excel的方法示例
一、准备工作
1、pom依赖
在pom.xml中加入POI的依赖
org.apache.poi poi-ooxml 3.11-beta1 org.apache.poi poi-ooxml-schemas 3.11-beta1
2、自定义注解
自定义注解,用于定义excel单元格的相关信息,用在需要导出的类上。
大家可以根据自己的实际需求来定义更多的内容。
@Retention(RetentionPolicy.RUNTIME)
public@interfaceExcelResources{
intorder()default9999;//定义字段在excel的单元格列坐标位置
Stringtitle()default"";//定义列坐标对应的标题
intcloumn()default100;//定义列宽
Stringpattern()default"";//定义日期显示格式
}
3、定义需要导出的实体
举例说明@ExcelResources的应用场景,我们创建一个demoModel,包含姓名、年龄、性别、日期。
后边的excel导出例子也采用这个实体类来举例。
@Data
publicclassExcelDemoModel{
@ExcelResources(order=0,title="姓名",cloumn=10)
privateStringname;
@ExcelResources(order=1,title="年龄",cloumn=10)
privateIntegerage;
@ExcelResources(order=2,title="创建时间",cloumn=24,pattern="yyyy-MM-ddHH:mm:ss")
privateDatecreateTime;
@ExcelResources(order=3,title="性别",cloumn=10)
privateSexTypesex;//枚举
}
4、定义导出辅助类
用于存放导出的excel对应标题和列宽
@Data
@NoArgsConstructor
@AllArgsConstructor
publicclassTitleAndCloumn{
privateStringtitle;//标题
privateintcloumn;//列宽
}
二、具体的导出方法
1、导出主要方法
@Service
publicclassExcelService{
privatestaticfloattitle_row_height=30;//标题行高
privatestaticfloatdata_row_height=25;//数据行高
publicvoidexportExcel(HttpServletRequestrequest,HttpServletResponseresponse,StringfileName,List>excelDatas,Class>clz){
try{
HSSFWorkbookresultWb=newHSSFWorkbook();
HSSFSheetsheet=resultWb.createSheet();//创建sheet
//根据类类型信息获取导出的excel对应的标题和列宽key-列号,value-标题和列宽
HashMaporderTitleAndCloumnMap=getTitleAndCloumnMap(clz);
//设置列宽
orderTitleAndCloumnMap.forEach((k,v)->{
sheet.setColumnWidth(k,v.getCloumn()*256);
});
HSSFRowrow0=sheet.createRow(0);
//设置标题行高
row0.setHeightInPoints(title_row_height);
//创建标题单元格格式
HSSFCellStyletitleCellStyle=getCellStyle(resultWb,11,true,HSSFColor.BLACK.index);
//填充标题行内容
orderTitleAndCloumnMap.forEach((k,v)->{
HSSFCellrow0Cell=row0.createCell(k);
row0Cell.setCellValue(v.getTitle());
row0Cell.setCellStyle(titleCellStyle);
});
//创建正文单元格格式
HSSFCellStyledataStyle=getCellStyle(resultWb,11,false,HSSFColor.BLACK.index);
//将正文转换为excel数据
introwNum=1;
for(Objectdata:excelDatas){
HSSFRowrow=sheet.createRow(rowNum++);
row.setHeightInPoints(data_row_height);
//获取对象值key-列号value-String值
HashMaporderValueMap=getValueMap(data);
orderValueMap.forEach((k,v)->{
HSSFCellcell=row.createCell(k);
cell.setCellValue(v);
cell.setCellStyle(dataStyle);
}
);
}
StringdownFileName=fileName+".xls";
response.setContentType("application/vnd.ms-excel;charset=UTF-8");//application/x-download
response.setHeader("Content-Disposition","attachment;"
+encodeFileName(request,downFileName));
OutputStreamoutputStream=response.getOutputStream();
resultWb.write(outputStream);
outputStream.flush();
outputStream.close();
resultWb.close();
}catch(Exceptione1){
e1.printStackTrace();
}
}
}
2、通过反射获取excel标题和列宽
/** *获取类的属性对应单元格标题和列宽 *@param *@return */ privatestaticHashMapgetTitleAndCloumnMap(Class>clz){ HashMap orderTitleAndCloumnMap=newHashMap<>(); Field[]fs=clz.getDeclaredFields(); for(Fieldf:fs){ f.setAccessible(true); if(f.isAnnotationPresent(ExcelResources.class)){ Integerorder=f.getAnnotation(ExcelResources.class).order(); Stringtitle=f.getAnnotation(ExcelResources.class).title(); intcloumn=f.getAnnotation(ExcelResources.class).cloumn(); TitleAndCloumntitleAndCloumn=newTitleAndCloumn(title,cloumn); orderTitleAndCloumnMap.put(order,titleAndCloumn); } } returnorderTitleAndCloumnMap; }
3、创建CellStyle
通过传入参数定义简单地CellStyle
publicHSSFCellStylegetCellStyle(HSSFWorkbookworkbook,intfontSize,booleanisBoleaWeight,shortcolor){
HSSFCellStylestyle=workbook.createCellStyle();
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);//水平居中
style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);//垂直居中
style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
style.setBorderRight(HSSFCellStyle.BORDER_THIN);
style.setBorderTop(HSSFCellStyle.BORDER_THIN);
HSSFFontfont=workbook.createFont();
font.setFontHeightInPoints((short)fontSize);//字号
font.setColor(color);//颜色
font.setFontName("宋体");//字体
if(isBoleaWeight){
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);//字体加粗
}
style.setWrapText(true);
style.setFont(font);
returnstyle;
}
4、通过反射获取对象信息并处理成String字符串
我这里只涉及到基本数据类型和Date以及枚举的值获取和转换,小伙伴可以根据自己的实际情况进行修改。
/** *获取对象的属性对应单元格坐标和值的键值对 *@paramobj *@return */ privatestaticHashMapgetValueMap(Objectobj)throwsIllegalAccessException{ HashMap result=newHashMap<>(); Class>clz=obj.getClass(); Field[]fs=clz.getDeclaredFields(); for(Fieldf:fs){ f.setAccessible(true); if(f.isAnnotationPresent(ExcelResources.class)){ Integerorder=f.getAnnotation(ExcelResources.class).order(); Stringvalue=""; ObjectvalueObj=f.get(obj); if(valueObj!=null){ //日期格式进行特殊处理 if(f.getType()==Date.class){ Stringpattern=f.getAnnotation(ExcelResources.class).pattern(); if(StringUtils.isEmpty(pattern)){ pattern="yyyy-MM-ddHH:mm:ss"; } SimpleDateFormatsdf=newSimpleDateFormat(pattern); value=sdf.format(valueObj); }else{ value=valueObj.toString();//其他格式调用toString方法,这里枚举就需要定义自己的toString方法 } } result.put(order,value); } } returnresult; }
5、枚举的定义
如果有用到枚举存储在数据库的小伙伴,可以自定义枚举的toString方法来实现excel导出时候相应的内容
publicenumSexType{
male("男"),
female("女"),
;
privateStringtypeName;
SexType(StringtypeName){
this.typeName=typeName;
}
@Override
publicStringtoString(){
returntypeName;
}
}
6、encodeFileName
/**
*根据不同的浏览器生成不同类型中文文件名编码
*
*@paramrequest
*@paramfileName
*@return
*@throwsUnsupportedEncodingException
*/
publicstaticStringencodeFileName(HttpServletRequestrequest,StringfileName)
throwsUnsupportedEncodingException
{
Stringnew_filename=URLEncoder.encode(fileName,"UTF8").replaceAll("\\+","%20");
Stringagent=request.getHeader("USER-AGENT").toLowerCase();
if(null!=agent&&-1!=agent.indexOf("msie"))
{
/**
*IE浏览器,只能采用URLEncoder编码
*/
return"filename=\""+new_filename+"\"";
}elseif(null!=agent&&-1!=agent.indexOf("applewebkit")){
/**
*Chrome浏览器,只能采用ISO编码的中文输出
*/
return"filename=\""+newString(fileName.getBytes("UTF-8"),"ISO8859-1")+"\"";
}elseif(null!=agent&&-1!=agent.indexOf("opera")){
/**
*Opera浏览器只可以使用filename*的中文输出
*RFC2231规定的标准
*/
return"filename*="+new_filename;
}elseif(null!=agent&&-1!=agent.indexOf("safari")){
/**
*Safani浏览器,只能采用iso编码的中文输出
*/
return"filename=\""+newString(fileName.getBytes("UTF-8"),"ISO8859-1")+"\"";
}elseif(null!=agent&&-1!=agent.indexOf("firefox"))
{
/**
*Firfox浏览器,可以使用filename*的中文输出
*RFC2231规定的标准
*/
return"filename*="+new_filename;
}else
{
return"filename=\""+new_filename+"\"";
}
}
三、方法调用案例
1、方法调用
publicvoidexportExcelDemo(HttpServletRequestrequest,HttpServletResponseresponse){
//一系列查询处理
ListdemoList=newArrayList<>();
excelService.exportExcel(request,response,"人员信息demo",demoList,ExcelDemoModel.class);
}
2、导出效果
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。