最近在做一个基于React+antd前端框架的Excel导出功能,我主要在后端做了处理,这个功能完成后,便总结成一篇技术分享文章,感兴趣的小伙伴可以参考该分享来做导出excle表格功能,以下步骤同样适用于vue框架,或者JSP页面的实现。

在做这类导出文件的功能,其实,在后端进行处理,会更容易些,虽然前端也可以进行处理,但还是建议后端来做,因为很多导出工具类基本都是很好用。

根据以下步骤,可以很容易就实现导出Excel表格数据的功能。

1.导出图标

按钮代码:

 <Button type="primary" onClick={this.excelPort} >导出</Button>

2.按钮this.excelToPort的方法:

 excelPort = () => {
location.href="/test/export.do"
}

3.建立Excel的Entity类(以下类可以直接复制用,无需做修改):

Excel Bean

 package com.test;

 import lombok.Getter;
import lombok.Setter;
import org.apache.poi.xssf.usermodel.XSSFCellStyle; @Getter
@Setter
public class ExcelBean {
private String headTextName; //列头(标题)名
private String propertyName; //对应字段名
private Integer cols; //合并单元格数
private XSSFCellStyle cellStyle; public ExcelBean(String headTextName, String propertyName, Integer cols) {
super();
this.headTextName = headTextName;
this.propertyName = propertyName;
this.cols = cols;
} }

映射到数据库里的User Bean

 package com.bqs.data.dcm.bean;

 import lombok.Getter;
import lombok.Setter; @Getter
@Setter
public class User {
private String id;
private String name;
private Integer age;
private String sex; }

4.建立Excel的工具类(无需修改可直接复制用)

 package com.test;

 import java.beans.IntrospectionException;
import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map; import com.test.ExcelBean;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook; /**
* @author 朱季谦
* @version
*/
public class ExportUtil { /**
* 导出Excel表
* @param clazz 数据源model类型
* @param objs excel标题以及对应的model字段
* @param map 标题行数以及cell字体样式
* @param sheetName 工作簿名称
* @return
*
*/
public static XSSFWorkbook createExcelFile(
Class<?> clazz,
List<Map<String,Object>> objs,
Map<Integer,List<ExcelBean>> map,
String sheetName) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException{
//创建新的工作簿
XSSFWorkbook workbook = new XSSFWorkbook();
//创建工作表
XSSFSheet sheet = workbook.createSheet(sheetName);
//设置excel的字体样式以及标题与内容的创建
createFont(workbook);//字体样式
createTableHeader(sheet,map);//创建标题
createTableRows(sheet,map,objs,clazz);//创建内容
System.out.println(workbook);
return workbook;
}
private static XSSFCellStyle fontStyle;
private static XSSFCellStyle fontStyle2;
private static void createFont(XSSFWorkbook workbook) {
//表头
fontStyle = workbook.createCellStyle();
XSSFFont font1 = workbook.createFont();
font1.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD);
font1.setFontName("黑体");
font1.setFontHeightInPoints((short) 12);//字体大小
fontStyle.setFont(font1);
fontStyle.setBorderBottom(XSSFCellStyle.BORDER_THIN);//下边框
fontStyle.setBorderLeft(XSSFCellStyle.BORDER_THIN);//左边框
fontStyle.setBorderTop(XSSFCellStyle.BORDER_THIN);//右边框
fontStyle.setBorderRight(XSSFCellStyle.BORDER_THIN);//右边框
fontStyle.setAlignment(XSSFCellStyle.ALIGN_CENTER);//居中
//内容
fontStyle2 = workbook.createCellStyle();
XSSFFont font2 = workbook.createFont();
font2.setFontName("宋体");
font2.setFontHeightInPoints((short)10);
fontStyle2.setFont(font2);
fontStyle2.setBorderBottom(XSSFCellStyle.BORDER_THIN);//下边框
fontStyle2.setBorderLeft(XSSFCellStyle.BORDER_THIN);//左边框
fontStyle2.setBorderTop(XSSFCellStyle.BORDER_THIN);//右边框
fontStyle2.setBorderRight(XSSFCellStyle.BORDER_THIN);//右边框
fontStyle2.setAlignment(XSSFCellStyle.ALIGN_CENTER);//居中
} /**
* 根据ExcelMapping 生成列头(多行列头)
* @param sheet 工作簿
* @param map 每行每个单元格对应的列头信息
*/
private static void createTableHeader(
XSSFSheet sheet,
Map<Integer, List<ExcelBean>> map) {
int startIndex = 0;//cell起始位置
int endIndex = 0;//cell终止位置
for(Map.Entry<Integer,List<ExcelBean>> entry: map.entrySet()){
XSSFRow row = sheet.createRow(entry.getKey()); //创建行
List<ExcelBean> excels = entry.getValue();
for(int x=0;x<excels.size();x++){
//合并单元格
if(excels.get(x).getCols()>1){
if(x==0){
endIndex += excels.get(x).getCols()-1;
//合并单元格CellRangeAddress构造参数依次表示起始行,截至行,起始列, 截至列
sheet.addMergedRegion(new CellRangeAddress(0, 0, startIndex, endIndex));
startIndex += excels.get(x).getCols();
}else{
endIndex += excels.get(x).getCols();
sheet.addMergedRegion(new CellRangeAddress(0, 0, startIndex, endIndex));
startIndex += excels.get(x).getCols();
}
XSSFCell cell = row.createCell(startIndex-excels.get(x).getCols());
//设置内容
cell.setCellValue(excels.get(x).getHeadTextName());
if(excels.get(x).getCellStyle() != null){
//设置格式
cell.setCellStyle(excels.get(x).getCellStyle());
}
cell.setCellStyle(fontStyle);
}else{
XSSFCell cell = row.createCell(x);
//设置内容
cell.setCellValue(excels.get(x).getHeadTextName());
if(excels.get(x).getCellStyle() != null){
//设置格式
cell.setCellStyle(excels.get(x).getCellStyle());
}
cell.setCellStyle(fontStyle);
}
}
}
} /**
* 为excel表中循环添加数据
* @param sheet
* @param map 字段名
* @param objs 查询的数据
* @param clazz 无用
*/
private static void createTableRows(
XSSFSheet sheet,
Map<Integer,List<ExcelBean>> map,
List<Map<String,Object>> objs,
Class<?> clazz)
throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
int rowindex = map.size();
int maxkey = 0;
List<ExcelBean> ems = new ArrayList<>();
for(Map.Entry<Integer,List<ExcelBean>> entry : map.entrySet()){
if(entry.getKey() > maxkey){
maxkey = entry.getKey();
}
}
ems = map.get(maxkey);
List<Integer> widths = new ArrayList<Integer>(ems.size());
for(Map<String,Object> obj : objs){
XSSFRow row = sheet.createRow(rowindex);
for(int i=0;i<ems.size();i++){
ExcelBean em = (ExcelBean)ems.get(i);
String propertyName = em.getPropertyName();
Object value = obj.get(propertyName);
XSSFCell cell = row.createCell(i);
String cellValue = "";
if("valid".equals(propertyName)){
cellValue = value.equals(1)?"启用":"禁用";
}else if(value==null){
cellValue = "";
}else if(value instanceof Date){
cellValue = new SimpleDateFormat("yyyy-MM-dd").format(value);
}else{
cellValue = value.toString();
}
cell.setCellValue(cellValue);
cell.setCellType(XSSFCell.CELL_TYPE_STRING);
cell.setCellStyle(fontStyle2);
sheet.autoSizeColumn(i);
}
rowindex++;
} //设置列宽
for(int index=0;index<widths.size();index++){
Integer width = widths.get(index);
width = width<2500?2500:width+300;
width = width>10000?10000+300:width+300;
sheet.setColumnWidth(index, width);
}
}
}

5.导出Excel的controller类

    /**
* 导出excle表格
*/
@RequestMapping(value = "/export")
public void exportTotal( HttpServletResponse response ) throws Exception{
response.reset(); //清除buffer缓存
//Map<String,Object> map=new HashMap<String,Object>();
// 指定下载的文件名
response.setContentType("application/vnd.ms-excel;charset=UTF-8");
String excleName="统计表格"+".xlsx";
response.setHeader("Content-Disposition","attachment;filename="+new String(excleName.getBytes(),"iso-8859-1"));
//导出Excel对象
XSSFWorkbook workbook = sysExportExcelInfo.exportExcel();
OutputStream output;
try {
output = response.getOutputStream();
BufferedOutputStream bufferedOutput = new BufferedOutputStream(output);
bufferedOutput.flush();
workbook.write(bufferedOutput);
bufferedOutput.close(); } catch (IOException e) {
e.printStackTrace();
}
}

6.导出Excel的service类

   public XSSFWorkbook exportExcel() throws Exception{
//获取dao导出的list集合
List<User> list=userService.exportUser(); List<Map<String,Object>> listMap=ListBeanToListMap(list); List<ExcelBean> excel = new ArrayList<>();
Map<Integer,List<ExcelBean>> map = new LinkedHashMap<>();
//设置标题栏
excel.add(new ExcelBean("序号","id",0));
excel.add(new ExcelBean("名字","name",0));
excel.add(new ExcelBean("年龄","age",0)); map.put(0,excel);
String sheetName = "统计表格";
//调用ExcelUtil方法
XSSFWorkbook xssfWorkbook = ExportUtil.createExcelFile(DcmDemand.class, listMap, map, sheetName);
System.out.println(xssfWorkbook);
return xssfWorkbook;
}

注意:整块导出Excel代码,主要需要改动只是这一行代码:List<User> list=userService.exportUser(),这是调用dao层获取以列表list获得数据的查询。

下面三行代码里的“序号”,“名字”,“年龄”根据User属性来定义的,它将作为表格表头呈现在导出的表格里。这里的User表映射到数据库表t_user表,你需要导出User里哪些字段的数据,就以这样格式excel.add(new ExcelBean("序号","id",0))加到下面代码里:

 excel.add(new ExcelBean("序号","id",0));
excel.add(new ExcelBean("名字","name",0));
excel.add(new ExcelBean("年龄","age",0));

其中,以上代码需要把list<String>转换成List<Map<String,Object>>形式,转换方法如下,因为创建表格时需要这样List<Map<String,Object>>格式类型数据:

  public static List<Map<String, Object>> ListBeanToListMap(List<User> list) throws NoSuchMethodException,
SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
List<Map<String, Object>> listmap = new ArrayList<Map<String, Object>>(); for (Object ob : list) { listmap.add(beanToMap(ob));
}
return listmap;
}

按照以上代码步骤,可以实现在React+antd前端实现导出这样的Excel表格功能:

若有什么不明白的,可以评论留言,我会尽量解答。

React+后端实现导出Excle表格的功能的更多相关文章

  1. 4-13 Webpacker-React.js; 用React做一个下拉表格的功能: <详解>

    Rails5.1增加了Webpacker: Webpacker essentially is the decisions made by the Rails team and bundled up i ...

  2. 前端 vue/react 或者 js 导入/导出 xlsx/xls (带样式)表格的功能

    第一种导出表格的功能: yarn add xlsx script-loader file-saver xlsx-style 效果展示 xlsx-style的bug修复:node_module/xlsx ...

  3. 数据库数据怎样导出成Excle表格或Word文档?

    数据导出:将数据库的数据导出成Excel工作表或Word文档 方法:将一个泛型集合导出出去 主要使用: SaveFileDialog StreamWriter 导出代码: private void b ...

  4. EasyUi通过POI 实现导出xls表格功能

    Spring +EasyUi+Spring Jpa(持久层) EasyUi通过POI 实现导出xls表格功能 EasyUi界面: 点击导出按钮实现数据导入到xls表格中 第一步:修改按钮事件: @Co ...

  5. java导入excle表格,并且对表格进行相应的修改,并对表格数据进行整理,最后导出本地表格等一系列操作

    1.首先创建一个java项目 完成效果如下图所示 2.导入以下jar包 3.代码如下 其中行和列的操作是根据需求自动划分的 public class auto_date { private stati ...

  6. 一个php将数据库的数据导出到excle表格中的小dome

    首先我们需要下载个PHPExcel,PHPExcel下载地址链接:https://pan.baidu.com/s/1nxpAc45 密码:qgct 下面来写个dome: <?php //把数据写 ...

  7. Vue中导出Excel表格方法

    本文记录一下在Vue中实现导出Excel表格的做法.参考度娘上各篇博客,最后实现功能 Excel表格,我的后端返回的是数据流,然后文件名是放进了content-disposition中,前端进行获取. ...

  8. PHP导入导出excel表格图片(转)

    写excel的时候,我用过pear的库,也用过pack压包的头,同样那些利用smarty等作的简单替换xml的也用过,csv的就更不用谈了.呵呵.(COM方式不讲了,这种可读的太多了,我也写过利用wp ...

  9. php:PHPExcel导出excel表格

    一.动态生成的内容如何能当成文件来下载呢? 方法:1.将Content-Type设置成application/octet-stream就可以了,即[header('Content-Type: appl ...

随机推荐

  1. HDFS 读写流程-译

    HDFS 文件读取流程 Client 端调用 DistributedFileSystem 对象的 open() 方法. 由 DistributedFileSystem 通过 RPC 向 NameNod ...

  2. np问题(大数阶乘取模)

    转自 np问题 题目描述: LYK 喜欢研究一些比较困难的问题,比如 np 问题. 这次它又遇到一个棘手的 np 问题.问题是这个样子的:有两个数 n 和 p,求 n 的阶乘对 p 取模后的结果. L ...

  3. js 大量数据优化,通用方法

    当页面渲染太多标签时,会出现卡顿的,典型就是类似table数据太多时,非常卡顿.如果选择分页,没必要讨论,这儿只讨论采用滚动的情况.解决思路很简单,就是页面不展示出来的元素,从页面上删除掉,最难点在于 ...

  4. 【Redis】SpringBoot+Redis+Ehcache实现二级缓存

    一.概述 1.1 一些疑惑? 1.2 场景 1.3 一级缓存.两级缓存的产生 1.4 流程分析 二.项目搭建 一.概述 1.1 一些疑惑? Ehcache本地内存 Redis 分布式缓存可以共享 一级 ...

  5. Netty源码分析 (六)----- 客户端连接接入accept过程

    通读本文,你会了解到1.netty如何接受新的请求2.netty如何给新请求分配reactor线程3.netty如何给每个新连接增加ChannelHandler netty中的reactor线程 ne ...

  6. c语言实现字符指针(字符串)数组的排序

    需求: "ff555d", "114ddd", "114dd","aaa", "aaab", &qu ...

  7. Elasticsearch在Java中的增删改查

    public class ElasticAPI { private static RestClient restClient; static { restClient=RestClient.build ...

  8. 初始mqtt服务

    MQTT入门 概念 mqtt意为消息队列遥测传输,是IBM开发的一个即时通讯协议.由于其维护一个长连接以轻量级低消耗著称,所以常用于移动端消息推送服务开发. 协议格式 mqtt协议控制报文的格式包含三 ...

  9. Redis在新项目中的使用场景

    Redis在新项目中的使用场景 数据类型 使用场景 string 比如说,我想知道什么时候封锁一个Ip地址,Incrby命令(使用这个命令记录被访问的次数) Hash 存储用户的信息[id,name, ...

  10. d010:盈数、亏数和完全数

    题目: 对一个正整数N而言,将它除了本身以外所有的因子加起来的总和为S,如果S>N,则N为盈数,如果S<N,则N为亏数,而如果S=N,则N为完全数(Perfect Number).例如10 ...