业务实践篇2:基于antd的table表格excel简单导出实践

时间:2021-2-20 作者:admin

基于antd的table表格excel简单导出实践

本文主要内容:
1.介绍antd的table的基本属性
2.结合antd导出xlsx
3.介绍主要的特点:合并操作,多sheet导出
4.结合官网的例子进行演示

食用前提:对antd,react有一定的基础。

业务背景
antd的table表格展示比较方便,只要配置了相关的列属性和数据,就可以展示比较友好的前端页面表格了。如果我们想要基于table的数据显示导出antd表格的数据,怎么办?
本文主要是基于antd的table表格实现前端excel导出的简单实践,使用antd的table的dataSource和columns配置即可,实现了单元格合并和导出多个sheet。

1.介绍antd的table的基本属性


antd中table组件的属性介绍在antd官网有详细的介绍。这里主要介绍本文用到的属性。

  • column.title:列头显示文字。
  • column.dataIndex:列数据在数据项中对应的路径,这里用的是string类型,故解释为对应的对象名更合适。
  • column.width:列宽度。
  • column.colSpan:表头合并单元格数。
  • column.render:(重点)生成复杂数据的渲染函数,参数为当前行的值,当前行数据,和当前行索引。render可以返回一个字符串value,或者一个jsx对象,或者一个对象等,本文主要用到如下的render对象。
{ 
  children:value,
  props:{
      rowSpan:1, // 跨行数
    colSpan:1  // 跨列数 
  } 
}
  • table.dataSource:数据数组,即每一行的数据项。

2.结合antd导出xlsx


这里用到的导出excel的库是js-xlsx,很方便的就将json数据导出为Excel文件。
导出的流程为:
1.新建工作簿(workBook);
2. 新建一个工作表(Sheets);
3. 构建数据项对象数组,由于antd中table的dataSource本身就是一个数据项对象数组,可以使用json转sheet函数,故这里直接使用dataSource和columns配置构建出json对象数据即可。
4.基本样式处理:主要设置列宽和合并操作;
5.工作薄添加sheet;
6.导出excel表格。

0.引入xlsx库

import XLSX from 'xlsx';

1.新建一个工作薄

var wb = XLSX.utils.book_new();

2.新建一个工作表&构建数据项对象数组
每一个单元格是一个对象,主要含有v,s,t等字段,v是原始值,s是表格样式,t是内容类型。这里主要使用v字段,默认是字符串类型。
以下data是数据项数组,columns是列属性配置数组。

let table = new Array();
data.forEach((item: any, i: number) => {
  let row: DerictoryObj<any> = {};
  columns.forEach((el: any) => {
    if (el.render) {
      if (typeof el.render === 'function') {
        const render = el.render(item[el.dataIndex], item, i);
        row[el.title] = {
          v: render ? (render.children ? render.children : render) : '',
        };
      } else {
        const render = el.render(item[el.dataIndex], item, i);
        row[el.title] = { v: render || '' };
      }
    } else {
      row[el.title] = { v: item[el.dataIndex] };
    }
  });
  table.push(row);
});

//json转sheet
var ws = XLSX.utils.json_to_sheet(table);

这里使用json_to_sheet函数将json数据转化为sheet,该函数接受处理好的json对象作为参数。
比较重要的一点是,如果column项含有render函数,说明数据需要进一步处理。所以判断column存在render,且render是函数,即调用render函数返回最终的结果。对于jsx对象,本文不做兼容处理。

3.设置列属性

//设置列宽
      ws['!cols'] = columns.map((item: any) => {
        if (item.width) {
          return { width: item.width / 5 };
        } else {
          return { width: 20 };
        }
      });

4.工作簿添加sheet

//sheet写入book
XLSX.utils.book_append_sheet(wb, ws, sheetName); // wb:工作簿,ws:工作表,sheetName:工作表名

5.导出excel

// 导出数据
XLSX.writeFile(wb, fileName + '.xlsx');

3.介绍主要的操作:合并操作,多sheet导出


(1)合并操作:
合并操作,需要用到的是ws中的 ‘!merges’ 对象。分别需要处理列表头的合并和数据单元的合并。列表头的合并只处理列合并,数据单元的合并处理列合并和行合并。
合并属性介绍:

ws['!merges'] = [{
    s:{  // s为开始的单元格
    r:1, // r为行数,从0开始
    c:2  // c为列数,从0开始
  },
  e:{  // e为结束的单元格
      r:2,
    c:2
  }
}]
  • 列表头的合并:
// 表格表头合并设置
const headerMerges = columns && columns.reduce((t: any, el: any, c: number) => {
  const { colSpan } = el;
  if (colSpan && colSpan > 0) {
    return [
      ...t,
      {
        s: { r: 0, c: c },
        e: { r: 0, c: c + colSpan - 1 }
      },
    ]
  }
  return t;
}, [])
  • 数据单元合并:
const dataMerges =
      data &&
      data.length > 0 &&
      data.reduce((total: any, item: any, r: number) => {
        return [
          ...total,
          ...columns.reduce((t: any, el: any, c: number) => {
            const span = el.render && el.render(item[el.dataIndex], item, r)?.props;
            let colSpan, rowSpan;
            if (span) {
              colSpan = span?.colSpan;
              rowSpan = span?.rowSpan;
            }
              if ((rowSpan && rowSpan > 1) || (colSpan && colSpan > 1)) {
                return [
                  ...t,
                  {
                    s: { r: r + 1, c: c },
                    e: { r: rowSpan ? (r + rowSpan) : (r + 1), c: colSpan ? c + colSpan - 1 : c }
                  },
                ];
              }
              return t;
            }, []),
          ];
        }, []);

由于数据单元的的合并属性rowSpan和colSpan属性是通过render属性获得的,所以需要遍历data和colums的进行属性合并扫描。

  • 合并列合并和数据单元格合并:
ws['!merges'] = [...headerMerges, ...dataMerges];

(2)工作簿中添加多个sheet:

XLSX.utils.book_append_sheet(wb, ws, sheetName); 

wb为工作薄,ws为工作表,sheetName为工作表的名称,可以多次插入工作表。

4.实例演示


以antd的官网例子为例:

(本图是antd官网例子截图)
实现导出这个表格的excel,当然这里进行了一些处理,本文代码不支持jsx。
结果截图如下:

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。