SpringBoot整合POI导出通用Excel的方法示例

网友投稿 921 2023-04-25

SpringBoot整合POI导出通用Excel的方法示例

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 @interface ExcelResources {

int order() default 9999;//定义字段在excel的单元格列坐标位置

String title() default "";//定义列坐标对应的标题

int cloumn() default 100;//定义列宽

String pattern() default "";//定义日期显示格式

}

3、定义需要导出的实体

举例说明@ExcelResources 的应用场景,我们创建一个demoModel,包含姓名、年龄、性别、日期。

后边的excel导出例子也采用这个实体类来举例。

@Data

public class ExcelDemoModel {

@ExcelResources(order=0,title = "姓名",cloumn = 10)

private String name;

@ExcelResources(order=1,title = "年龄",cloumn = 10)

private Integer age;

@ExcelResources(order=2,title = "创建时间",cloumn = 24,pattern = "yyyy-MM-dd HH:mm:ss")

private Date createTime;

@ExcelResources(order=3,title = "性别",cloumn = 10)

private SexType sex;//枚举

}

4、定义导出辅助类

用于存放导出的excel对应标题和列宽

@Data

@NoArgsConstructor

@AllArgsConstructor

public class TitleAndCloumn {

private String title;//标题

private int cloumn;//列宽

}

二、具体的导出方法

1、导出主要方法

@Service

public class ExcelService {

private static float title_row_height=30;//标题行高

private static float data_row_height=25;//数据行高

public void exportExcel(HttpServletRequest request, HttpServletResponse response, String fileName ,List> excelDatas,Class> clz ) {

try {

HSSFWorkbook resultWb=new HSSFWorkbook();

HSSFSheet sheet=resultWb.createSheet();//创建sheet

//根据类类型信息获取导出的excel对应的标题和列宽 key-列号,value-标题和列宽

HashMap<Integer, TitleAndCloumn> orderTitleAndCloumnMap=getTitleAndCloumnMap(clz);

//设置列宽

orderTitleAndCloumnMap.forEach((k,v) -> {

sheet.setColumnWidth(k, v.getCloumn()*256);

});

HSSFRow row0=sheet.createRow(0);

//设置标题行高

row0.setHeightInPoints(title_row_height);

//创建标题单元格格式

HSSFCellStyle titleCellStyle=getCellStyle(resultWb,11,true,HSSFColor.BLACK.index);

//填充标题行内容

orderTitleAndCloumnMap.forEach((k,v) -> {

HSSFCell row0Cell=row0.createCell(k);

row0Cell.setCellValue(v.getTitle());

row0Cell.setCellStyle(titleCellStyle);

});

//创建正文单元格格式

HSSFCellStyle dataStyle = getCellStyle(resultWb,11,false,HSSFColor.BLACK.index);

//将正文转换为excel数据

int rowNum=1;

for(Object data:excelDatas){

HSSFRow row=sheet.createRow(rowNum++);

row.setHeightInPoints(data_row_height);

//获取对象值 key-列号 value-String值

HashMap orderValueMap=getValueMap(data);

orderValueMap.forEach((k,v) ->{

HSSFCell cell=row.createCell(k);

cell.setCellValue(v);

cell.setCellStyle(dataStyle);

}

);

}

String downFileName=fileName+".xls";

response.setContentType("application/vnd.ms-excel; charset=UTF-8");// application/x-download

response.setHeader("Content-Disposition", "attachment; "

+encodeFileName(request, downFileName));

OutputStream outputStream = response.getOutputStream();

resultWb.write(outputStream);

outputStream.flush();

outputStream.close();

resultWb.close();

}catch (Exception e1) {

e1.printStackTrace();

}

}

}

2、通过反射获取excel标题和列宽

/**

* 获取类的属性对应单元格标题和列宽

* @param

* @return

*/

private static HashMap getTitleAndCloumnMap(Class> clz) {

HashMap orderTitleAndCloumnMap=new HashMap<>();

Field[] fs = clz.getDeclaredFields();

for(Field f:fs) {

f.setAccessible(true);

if(f.isAnnotationPresent(ExcelResources.class)) {

Integer order=f.getAnnotation(ExcelResources.class).order();

String title=f.getAnnotation(ExcelResources.class).title();

int cloumn=f.getAnnotation(ExcelResources.class).cloumn();

TitleAndCloumn titleAndCloumn=new TitleAndCloumn(title,cloumn);

orderTitleAndCloumnMap.put(order,titleAndCloumn);

}

}

return orderTitleAndCloumnMap;

}

3、创建CellStyle

通过传入参数定义简单地CellStyle

public HSSFCellStyle getCellStyle(HSSFWorkbook workbook,int fontSize,boolean isBoleaWeight,short color){

HSSFCellStyle style = 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);

HSSFFont font = workbook.createFont();

font.setFontHeightInPoints((short) fontSize);//字号

font.setColor(color);//颜色

font.setFontName("宋体");//字体

if(isBoleaWeight){

font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); //字体加粗

}

style.setWrapText(true);

style.setFont(font);

return style;

}

4、通过反射获取对象信息并处理成String字符串

我这里只涉及到基本数据类型和Date以及枚举的值获取和转换,小伙伴可以根据自己的实际情况进行修改。

/**

* 获取对象的属性对应单元格坐标和值的键值对

* @param obj

* @return

*/

private static HashMap getValueMap(Object obj) throws IllegalAccessException {

HashMap result=new HashMap<>();

Class> clz=obj.getClass();

Field[] fs = clz.getDeclaredFields();

for(Field f:fs) {

f.setAccessible(true);

if(f.isAnnotationPresent(ExcelResources.class)) {

Integer order=f.getAnnotation(ExcelResources.class).order();

String value="";

Object valueObj=f.get(obj);

if(valueObj!=null) {

//日期格式进行特殊处理

if(f.getType()==Date.class){

String pattern=f.getAnnotation(ExcelResources.class).pattern();

if(StringUtils.isEmpty(pattern)){

pattern="yyyy-MM-dd HH:mm:ss";

}

SimpleDateFormat sdf=new SimpleDateFormat(pattern);

value=sdf.format(valueObj);

}else{

value=valueObj.toString();//其他格式调用toString方法,这里枚举就需要定义自己的toString方法

}

}

result.put(order, value);

}

}

return result;

}

5、枚举的定义

如果有用到枚举存储在数据库的小伙伴,可以自定义枚举的toString方法来实现excel导出时候相应的内容

public enum SexType {

male("男"),

female("女"),

;

private String typeName;

SexType(String typeName) {

this.typeName = typeName;

}

@Override

public String toString() {

return typeName;

}

}

6、encodeFileName

/**

* 根据不同的浏览器生成不同类型中文文件名编码

*

* @param request

* @param fileName

* @return

* @throws UnsupportedEncodingException

*/

public static String encodeFileName(HttpServletRequest request, String fileName)

throws UnsupportedEncodingException

{

String new_filename = URLEncoder.encode(fileName, "UTF8").replaceAll("\\+", "%20");

String agent = request.getHeader("USER-AGENT").toLowerCase();

if (null != agent && -1 != agent.indexOf("msie"))

{

/**

* IE浏览器,只能采用URLEncoder编码

*/

return "filename=\"" + new_filename +"\"";

}else if (null != agent && -1 != agent.indexOf("applewebkit")){

/**

* Chrome浏览器,只能采用ISO编码的中文输出

*/

return "filename=\"" + new String(fileName.getBytes("UTF-8"),"ISO8859-1") +"\"";

} else if (null != agent && -1 != agent.indexOf("opera")){

/**

* Opera浏览器只可以使用filename*的中文输出

* RFC2231规定的标准

*/

return "filename*=" + new_filename ;

}else if (null != agent && -1 != agent.indexOf("safari")){

/**

* Safani浏览器,只能采用iso编码的中文输出

*/

return "filename=\"" + new String(fileName.getBytes("UTF-8"),"ISO8859-1") +"\"";

}else if (null != agent && -1 != agent.indexOf("firefox"))

{

/**

* Firfox浏览器,可以使用filename*的中文输出

* RFC2231规定的标准

*/

return "filename*=" + new_filename ;

} else

{

return "filename=\"" + new_filename +"\"";

}

}

三、方法调用案例

1、方法调用

public void exportExcelDemo(HttpServletRequest request, HttpServletResponse response) {

//一系列查询处理

List demoList=new ArrayList<>();

excelService.exportExcel(request,response,"人员信息demo",demoList,ExcelDemoModel.class);

}

2、导出效果

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:详解IDEA使用Maven项目不能加入本地Jar包的解决方法
下一篇:Springboot实现根据条件切换注入不同实现类的示例代码
相关文章

 发表评论

暂时没有评论,来抢沙发吧~