最近在做一个基于React+antd前端框架的Excel导出功能,我主要在后端做了处理,这个功能完成后,便总结成一篇技术分享文章,感兴趣的小伙伴可以参考该分享来做导出excle表格功能,以下步骤同样适用于vue框架,或者JSP页面的实现。
在做这类导出文件的功能,其实,在后端进行处理,会更容易些,虽然前端也可以进行处理,但还是建议后端来做,因为很多导出工具类基本都是很好用。
根据以下步骤,可以很容易就实现导出Excel表格数据的功能。
1.导出图标
按钮代码:
1 <Button type="primary" onClick={this.excelPort} >导出</Button>
2.按钮this.excelToPort的方法:
1 excelPort = () => { 2 location.href="/test/export.do" 3 }
3.建立Excel的Entity类(以下类可以直接复制用,无需做修改):
Excel Bean
1 package com.test; 2 3 import lombok.Getter; 4 lombok.Setter; 5 org.apache.poi.xssf.usermodel.XSSFCellStyle; 6 7 @Getter 8 @Setter 9 public class ExcelBean { 10 private String headTextName; //列头(标题)名 11 private String propertyName; 对应字段名 12 private Integer cols; 合并单元格数 13 private XSSFCellStyle cellStyle; 14 15 public ExcelBean(String headTextName,String propertyName,Integer cols) { 16 super(); 17 this.headTextName = headTextName; 18 this.propertyName = propertyName; 19 this.cols = cols; 20 } 21 22 }
映射到数据库里的User Bean
com.bqs.data.dcm.bean; 5 6 User { 9 String id; String name; Integer age; String sex; 13 14 }
4.建立Excel的工具类(无需修改可直接复制用)
1 2 3 java.beans.IntrospectionException; 4 java.lang.reflect.InvocationTargetException; 5 java.text.SimpleDateFormat; 6 java.util.ArrayList; 7 java.util.Date; 8 java.util.List; 9 java.util.Map; 10 11 com.test.ExcelBean; 12 org.apache.poi.ss.util.CellRangeAddress; 13 org.apache.poi.xssf.usermodel.XSSFCell; 14 15 org.apache.poi.xssf.usermodel.XSSFFont; 16 org.apache.poi.xssf.usermodel.XSSFRow; 17 org.apache.poi.xssf.usermodel.XSSFSheet; 18 org.apache.poi.xssf.usermodel.XSSFWorkbook; 19 20 /** 21 * @author 朱季谦 22 @version 23 */ 24 ExportUtil { 25 26 27 * 导出Excel表 28 * @param clazz 数据源model类型 29 objs excel标题以及对应的model字段 30 map 标题行数以及cell字体样式 31 sheetName 工作簿名称 32 @return 33 * 34 35 static XSSFWorkbook createExcelFile( 36 Class<?> clazz, 37 List<Map<String,Object>> objs,1)"> 38 Map<Integer,List<ExcelBean>> map,1)"> 39 String sheetName) throws IllegalAccessException,IllegalArgumentException,InvocationTargetException,IntrospectionException{ 40 创建新的工作簿 41 XSSFWorkbook workbook = new XSSFWorkbook(); 42 创建工作表 43 XSSFSheet sheet = workbook.createSheet(sheetName); 44 设置excel的字体样式以及标题与内容的创建 45 createFont(workbook);字体样式 46 createTableHeader(sheet,map);创建标题 47 createTableRows(sheet,map,objs,clazz);创建内容 48 System.out.println(workbook); 49 return workbook; 50 51 private XSSFCellStyle fontStyle; 52 XSSFCellStyle fontStyle2; 53 static void createFont(XSSFWorkbook workbook) { 54 表头 55 fontStyle = workbook.createCellStyle(); 56 XSSFFont font1 = workbook.createFont(); 57 font1.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD); 58 font1.setFontName("黑体"); 59 font1.setFontHeightInPoints((short) 12);字体大小 60 fontStyle.setFont(font1); 61 fontStyle.setBorderBottom(XSSFCellStyle.BORDER_THIN);下边框 62 fontStyle.setBorderLeft(XSSFCellStyle.BORDER_THIN);左边框 63 fontStyle.setBorderTop(XSSFCellStyle.BORDER_THIN);右边框 64 fontStyle.setBorderRight(XSSFCellStyle.BORDER_THIN); 65 fontStyle.setAlignment(XSSFCellStyle.ALIGN_CENTER);居中 66 内容 67 fontStyle2 = 68 XSSFFont font2 = 69 font2.setFontName("宋体" 70 font2.setFontHeightInPoints((short)10 71 fontStyle2.setFont(font2); 72 fontStyle2.setBorderBottom(XSSFCellStyle.BORDER_THIN); 73 fontStyle2.setBorderLeft(XSSFCellStyle.BORDER_THIN); 74 fontStyle2.setBorderTop(XSSFCellStyle.BORDER_THIN); 75 fontStyle2.setBorderRight(XSSFCellStyle.BORDER_THIN); 76 fontStyle2.setAlignment(XSSFCellStyle.ALIGN_CENTER);居中 77 78 79 80 81 82 * 根据ExcelMapping 生成列头(多行列头) 83 sheet 工作簿 84 map 每行每个单元格对应的列头信息 85 86 createTableHeader( 87 XSSFSheet sheet,1)"> 88 Map<Integer,1)"> map) { 89 int startIndex = 0;cell起始位置 90 int endIndex = 0;cell终止位置 91 for(Map.Entry<Integer,1)"> entry: map.entrySet()){ 92 XSSFRow row = sheet.createRow(entry.getKey()); 创建行 93 List<ExcelBean> excels = entry.getValue(); 94 for(int x=0;x<excels.size();x++){ 95 合并单元格 96 if(excels.get(x).getCols()>1 97 if(x==0 98 endIndex += excels.get(x).getCols()-1; 99 合并单元格CellRangeAddress构造参数依次表示起始行,截至行,起始列, 截至列 100 sheet.addMergedRegion(new CellRangeAddress(0,0,startIndex,endIndex)); 101 startIndex += excels.get(x).getCols(); 102 }else{ 103 endIndex +=104 sheet.addMergedRegion(105 startIndex +=106 } 107 XSSFCell cell = row.createCell(startIndex-excels.get(x).getCols()); 108 设置内容 109 cell.setCellValue(excels.get(x).getHeadTextName()); 110 if(excels.get(x).getCellStyle() != null111 设置格式 112 cell.setCellStyle(excels.get(x).getCellStyle()); 113 114 cell.setCellStyle(fontStyle); 115 }116 XSSFCell cell = row.createCell(x); 117 118 119 120 121 122 123 124 } 125 } 126 } 127 128 129 130 131 * 为excel表中循环添加数据 132 sheet 133 map 字段名 134 objs 查询的数据 135 clazz 无用 136 137 createTableRows( 138 139 Map<Integer,1)">140 List<Map<String,1)">141 Class<?> clazz) 142 IntrospectionException,IllegalAccessException,InvocationTargetException { 143 int rowindex = map.size(); 144 int maxkey = 0145 List<ExcelBean> ems = new ArrayList<>146 entry : map.entrySet()){ 147 if(entry.getKey() > maxkey){ 148 maxkey = entry.getKey(); 149 150 151 ems = map.get(maxkey); 152 List<Integer> widths = new ArrayList<Integer>(ems.size()); 153 for(Map<String,Object> obj : objs){ 154 XSSFRow row = sheet.createRow(rowindex); 155 int i=0;i<ems.size();i++156 ExcelBean em = (ExcelBean)ems.get(i); 157 String propertyName = em.getPropertyName(); 158 Object value = obj.get(propertyName); 159 XSSFCell cell = row.createCell(i); 160 String cellValue = ""161 if("valid".equals(propertyName)){ 162 cellValue = value.equals(1)?"启用":"禁用"163 }else if(value==164 cellValue = ""165 }if(value instanceof Date){ 166 cellValue = new SimpleDateFormat("yyyy-MM-dd").format(value); 167 }168 cellValue = value.toString(); 169 170 cell.setCellValue(cellValue); 171 cell.setCellType(XSSFCell.CELL_TYPE_STRING); 172 cell.setCellStyle(fontStyle2); 173 sheet.autoSizeColumn(i); 174 175 rowindex++176 177 178 设置列宽 179 int index=0;index<widths.size();index++180 Integer width = widths.get(index); 181 width = width<2500?2500:width+300182 width = width>10000?10000+300:width+300183 sheet.setColumnWidth(index,width); 184 185 186 }
5.导出Excel的controller类
1 2 * 导出excle表格 3 4 @RequestMapping(value = "/export") 5 void exportTotal( HttpServletResponse response ) Exception{ 6 response.reset(); 清除buffer缓存 7 Map<String,Object> map=new HashMap<String,Object>(); 8 指定下载的文件名 9 response.setContentType("application/vnd.ms-excel;charset=UTF-8"10 String excleName="统计表格"+".xlsx"11 response.setHeader("Content-Disposition","attachment;filename="+new String(excleName.getBytes(),"iso-8859-1")); 12 导出Excel对象 13 XSSFWorkbook workbook = sysExportExcelInfo.exportExcel(); 14 OutputStream output; 15 try16 output = response.getOutputStream(); 17 BufferedOutputStream bufferedOutput = BufferedOutputStream(output); 18 bufferedOutput.flush(); 19 workbook.write(bufferedOutput); bufferedOutput.close(); 22 } catch (IOException e) { 23 e.printStackTrace(); 24 25 }
6.导出Excel的service类
1 public XSSFWorkbook exportExcel() 2 获取dao导出的list集合 3 List<User> list=userService.exportUser(); 4 5 List<Map<String,Object>> listMap=ListBeanToListMap(list); 7 List<ExcelBean> excel = 8 Map<Integer,List<ExcelBean>> map = new LinkedHashMap<> 9 设置标题栏 10 excel.add(new ExcelBean("序号","id",1)">11 excel.add(new ExcelBean("名字","name",1)">12 excel.add(new ExcelBean("年龄","age",1)">13 14 map.put(015 String sheetName = "统计表格"调用ExcelUtil方法 17 XSSFWorkbook xssfWorkbook = ExportUtil.createExcelFile(DcmDemand. System.out.println(xssfWorkbook); xssfWorkbook; 20 }
注意:整块导出Excel代码,主要需要改动只是这一行代码:List<User> list=userService.exportUser(),这是调用dao层获取以列表list获得数据的查询。
下面三行代码里的“序号”,“名字”,“年龄”根据User属性来定义的,它将作为表格表头呈现在导出的表格里。这里的User表映射到数据库表t_user表,你需要导出User里哪些字段的数据,就以这样格式excel.add(new ExcelBean("序号",0))加到下面代码里:
1 excel.add(2 excel.add(3 excel.add(代码需要把list<String>转换成List<Map<String,Object>>形式,转换方法如下,因为创建表格时需要这样List<Map<String,Object>>格式类型数据:1 static List<Map<String,Object>> ListBeanToListMap(List<User> list) NoSuchMethodException,1)"> SecurityException,1)"> 3 List<Map<String,Object>> listmap = new ArrayList<Map<String,1)"> 4 5 for (Object ob : list) { listmap.add(beanToMap(ob)); listmap; 10 }
按照以上代码步骤,可以实现在React+antd前端实现导出这样的Excel表格功能:
若有什么不明白的,可以评论留言,我会尽量解答。