百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

使用JavaScript实现前端导入和导出excel文件?(H5编辑器实战)

csdh11 2024-12-28 12:02 18 浏览

前言

最近笔者终于把H5-Dooring的后台管理系统初步搭建完成, 有了初步的数据采集和数据分析能力, 接下来我们就复盘一下其中涉及的几个知识点,并一一阐述其在Dooring H5可视化编辑器中的解决方案. 笔者将分成3篇文章来复盘, 主要解决场景如下: 如何使用JavaScript实现前端导入和导出excel文件(H5编辑器实战复盘) 前端如何基于table中的数据一键生成多维度数据可视化分析报表 * 如何实现会员管理系统下的权限路由和权限菜单

以上场景也是前端工程师在开发后台管理系统中经常遇到的或者即将遇到的问题, 本文是上述介绍中的第一篇文章, 你将收获: 使用JavaScript实现前端导入excel文件并自动生成可编辑的Table组件 使用JavaScript实现前端基于Table数据一键导出excel文件 * XLSXjs-export-excel基本使用

正文

本文接下来的内容素材都是基于H5可视化编辑器(H5-Dooring)项目的截图, 如果想实际体验, 可以访问H5-Dooring网站实际体验. 接下来我们直接开始我们的方案实现.

1. 使用JavaScript实现前端导入excel文件并自动生成可编辑的Table组件

在开始实现之前, 我们先来看看实现效果.

1.1 实现效果

导入excel文件并通过antdtable组件渲染table:

编辑table组件:

保存table数据后实时渲染可视化图表:

以上就是我们实现导入excel文件后, 编辑table, 最后动态生成图表的完整流程.

1.2 实现一键导入excel文件并生成table表格

导入excel文件的功能我们可以用javascript原生的方式实现解析, 比如可以用fileReader这些原生api,但考虑到开发效率和后期的维护, 笔者这里采用antdUpload组件XLSX来实现上传文件并解析的功能. 由于我们采用antdtable组件来渲染数据, 所以我们需要手动将解析出来的数据转换成table支持的数据格式.大致流程如下:

所以我们需要做的就是将Upload得到的文件数据传给xlsx, 由xlsx生成解析对象, 最后我们利用javascript算法将xlsx的对象处理成ant-table支持的数据格式即可. 这里我们用到了FileReader对象, 目的是将文件转化为BinaryString, 然后我们就可以用xlsxbinary模式来读取excel数据了, 代码如下:

// 解析并提取excel数据
let reader = new FileReader();
reader.onload = function(e) {
  let data = e.target.result;
  let workbook = XLSX.read(data, {type: 'binary'});
  let sheetNames = workbook.SheetNames; // 工作表名称集合
  let draftObj = {}
  sheetNames.forEach(name => {
    // 通过工作表名称来获取指定工作表
    let worksheet = workbook.Sheets[name]; 
    for(let key in worksheet) {
      // v是读取单元格的原始值
      if(key[0] !== '!') {
        if(draftObj[key[0]]) {
          draftObj[key[0]].push(worksheet[key].v)
        }else {
          draftObj[key[0]] = [worksheet[key].v]
        }
      }
    }
  });
  // 生成ant-table支持的数据格式
  let sourceData = Object.values(draftObj).map((item,i) => ({ key: i + '', name: item[0], value: item[1]}))

经过以上处理, 我们得到的sourceData即是ant-table可用的数据结构, 至此我们就实现了表格导入的功能.

1.3 table表格的编辑功能实现

table表格的编辑功能实现其实也很简单, 我们只需要按照antd的table组件提供的自定义行和单元格的实现方式即可. antd官网上也有实现可编辑表格的实现方案, 如下:

大家感兴趣的可以研究一下. 当然自己实现可编辑的表格也很简单, 而且有很多方式, 比如用columnrender函数来动态切换表格的编辑状态, 或者使用弹窗编辑等都是可以的.

1.4 根据编辑的table数据动态生成图表

根据table数据动态生成图表这块需要有一定的约定, 我们需要符合图表库的数据规范, 不过我们有了table数据, 处理数据规范当然是很简单的事情了, 笔者的可视化库采用antvf2实现, 所以需要做一层适配来使得f2能消费我们的数据.

还有一点就是为了能使用多张图表, 我们需要对f2的图表进行统一封装, 使其成为符合我们应用场景的可视化组件库.

我们先看看f2的使用的数据格式:

const data = [
  { genre: 'Sports', sold: 275 },
  { genre: 'Strategy', sold: 115 },
  { genre: 'Action', sold: 120 },
  { genre: 'Shooter', sold: 350 },
  { genre: 'Other', sold: 150 }
];

此数据格式会渲染成如下的图表:

所以说我们总结下来其主要有2个纬度的指标, 包括它们的面积图, 饼图, 折线图, 格式都基本一致, 所以我们可以基于这一点封装成组件的可视化组件, 如下:

import { Chart } from '@antv/f2';
import React, { memo, useEffect, useRef } from 'react';
import ChartImg from '@/assets/chart.png';

import styles from './index.less';
import { IChartConfig } from './schema';

interface XChartProps extends IChartConfig {
  isTpl: boolean;
}

const XChart = (props: XChartProps) => {
  const { isTpl, data, color, size, paddingTop, title } = props;
  const chartRef = useRef(null);
  useEffect(() => {
    if (!isTpl) {
      const chart = new Chart({
        el: chartRef.current || undefined,
        pixelRatio: window.devicePixelRatio, // 指定分辨率
      });

      // step 2: 处理数据
      const dataX = data.map(item => ({ ...item, value: Number(item.value) }));

      // Step 2: 载入数据源
      chart.source(dataX);

      // Step 3:创建图形语法,绘制柱状图,由 genre 和 sold 两个属性决定图形位置,genre 映射至 x 轴,sold 映射至 y 轴
      chart
        .interval()
        .position('name*value')
        .color('name');

      // Step 4: 渲染图表
      chart.render();
    }
  }, [data, isTpl]);
  return (
    <div className={styles.chartWrap}>
      <div className={styles.chartTitle} style={{ color, fontSize: size, paddingTop }}>
        {title}
      </div>
      {isTpl ? <img src={ChartImg} alt="dooring chart" /> : <canvas ref={chartRef}></canvas>}
    </div>
  );
};

export default memo(XChart);

当然其他的可视化组件也可以用相同的模式封装,这里就不一一举例了. 以上的组件封装使用reacthooks组件, vue的也类似, 基本原理都一致.

2. 使用JavaScript实现前端基于Table数据一键导出excel文件

同样的, 我们实现将table数据一键导出为excel也是类似, 不过方案有所不同, 我们先来看看在Dooring中的实现效果.

2.1 一键导出为excel实现效果


以上就是用户基于后台采集到的数据, 一键导出excel文件的流程, 最后一张图是生成的excel文件在office软件中的呈现.

2.2 使用javascript实现一键导出excel文件功能

一键导出功能主要用在H5-Dooring的后台管理页面中, 为用户提供方便的导出数据能力. 我们这里导出功能也依然能使用xlsx来实现, 但是综合对比了一下笔者发现有更简单的方案, 接下来笔者会详细介绍, 首先我们还是来看一下流程:

很明显我们的导出流程比导入流程简单很多, 我们只需要将table的数据格式反编译成插件支持的数据即可. 这里笔者使用了js-export-excel来做文件导出, 使用它非常灵活,我们可以自定义: 自定义导出的excel文件名 自定义excel的过滤字段 * 自定义excel文件中每列的表头名称

由于js-export-excel支持的数据结构是数组对象, 所以我们需要花点功夫把table的数据转换成数组对象, 其中需要注意的是ant的table数据结构中键对应的值可以是数组, 但是js-export-excel键对应的值是字符串, 所以我们要把数组转换成字符串,如[a,b,c]变成'a,b,c', 所以我们需要对数据格式进行转换, 具体实现如下:

const generateExcel = () => {
    let option = {};  //option代表的就是excel文件
    let dataTable = [];  //excel文件中的数据内容
    let len = list.length;
    if (len) {
        for(let i=0; i<len; i++) {
            let row = list[i];
            let obj:any = {};
            for(let key in row) {
                if(typeof row[key] === 'object') {
                    let arr = row[key];
                    obj[key] = arr.map((item:any) => (typeof item === 'object' ? item.label : item)).join(',')
                }else {
                    obj[key] = row[key]
                }
            }
            dataTable.push(obj);  //设置excel中每列所获取的数据源
        }
    }
    let tableKeys = Object.keys(dataTable[0]);
    option.fileName = tableName;  //excel文件名称
    option.datas = [
          {
            sheetData: dataTable,  //excel文件中的数据源
            sheetName: tableName,  //excel文件中sheet页名称
            sheetFilter: tableKeys,  //excel文件中需显示的列数据
            sheetHeader: tableKeys,  //excel文件中每列的表头名称
          }
    ]
    let toExcel = new ExportJsonExcel(option);  //生成excel文件
    toExcel.saveExcel();  //下载excel文件
  }

注意, 以上笔者实现的方案对任何table组件都使用, 可直接使用以上代码在大多数场景下使用. 至此, 我们就实现了使用JavaScript实现前端导入和导出excel文件的功能.

所以, 今天你又博学了吗?

最后

以上教程笔者已经集成到H5-Dooring中,对于一些更复杂的交互功能,通过合理的设计也是可以实现的,大家可以自行探索研究。

地址:H5-Dooring | 一款强大的H5编辑器

如果想学习更多H5游戏, webpack,node,gulp,css3,javascript,nodeJS,canvas数据可视化等前端知识和实战,欢迎在《趣谈前端》一起学习讨论,共同探索前端的边界。

相关推荐

探索Java项目中日志系统最佳实践:从入门到精通

探索Java项目中日志系统最佳实践:从入门到精通在现代软件开发中,日志系统如同一位默默无闻却至关重要的管家,它记录了程序运行中的各种事件,为我们排查问题、监控性能和优化系统提供了宝贵的依据。在Java...

用了这么多年的java日志框架,你真的弄懂了吗?

在项目开发过程中,有一个必不可少的环节就是记录日志,相信只要是个程序员都用过,可是咱们自问下,用了这么多年的日志框架,你确定自己真弄懂了日志框架的来龙去脉嘛?下面笔者就详细聊聊java中常用日志框架的...

物理老师教你学Java语言(中篇)(物理专业学编程)

第四章物质的基本结构——类与对象...

一文搞定!Spring Boot3 定时任务操作全攻略

各位互联网大厂的后端开发小伙伴们,在使用SpringBoot3开发项目时,你是否遇到过定时任务实现的难题呢?比如任务调度时间不准确,代码报错却找不到方向,是不是特别头疼?如今,随着互联网业务规模...

你还不懂java的日志系统吗 ?(java的日志类)

一、背景在java的开发中,使用最多也绕不过去的一个话题就是日志,在程序中除了业务代码外,使用最多的就是打印日志。经常听到的这样一句话就是“打个日志调试下”,没错在日常的开发、调试过程中打印日志是常干...

谈谈枚举的新用法--java(java枚举的作用与好处)

问题的由来前段时间改游戏buff功能,干了一件愚蠢的事情,那就是把枚举和运算集合在一起,然后运行一段时间后buff就出现各种问题,我当时懵逼了!事情是这样的,做过游戏的都知道,buff,需要分类型,且...

你还不懂java的日志系统吗(javaw 日志)

一、背景在java的开发中,使用最多也绕不过去的一个话题就是日志,在程序中除了业务代码外,使用最多的就是打印日志。经常听到的这样一句话就是“打个日志调试下”,没错在日常的开发、调试过程中打印日志是常干...

Java 8之后的那些新特性(三):Java System Logger

去年12月份log4j日志框架的一个漏洞,给Java整个行业造成了非常大的影响。这个事情也顺带把log4j这个日志框架推到了争议的最前线。在Java领域,log4j可能相对比较流行。而在log4j之外...

Java开发中的日志管理:让程序“开口说话”

Java开发中的日志管理:让程序“开口说话”日志是程序员的朋友,也是程序的“嘴巴”。它能让程序在运行过程中“开口说话”,告诉我们它的状态、行为以及遇到的问题。在Java开发中,良好的日志管理不仅能帮助...

吊打面试官(十二)--Java语言中ArrayList类一文全掌握

导读...

OS X 效率启动器 Alfred 详解与使用技巧

问:为什么要在Mac上使用效率启动器类应用?答:在非特殊专业用户的环境下,(每天)用户一般可以在系统中进行上百次操作,可以是点击,也可以是拖拽,但这些只是过程,而我们的真正目的是想获得结果,也就是...

Java中 高级的异常处理(java中异常处理的两种方式)

介绍异常处理是软件开发的一个关键方面,尤其是在Java中,这种语言以其稳健性和平台独立性而闻名。正确的异常处理不仅可以防止应用程序崩溃,还有助于调试并向用户提供有意义的反馈。...

【性能调优】全方位教你定位慢SQL,方法介绍下!

1.使用数据库自带工具...

全面了解mysql锁机制(InnoDB)与问题排查

MySQL/InnoDB的加锁,一直是一个常见的话题。例如,数据库如果有高并发请求,如何保证数据完整性?产生死锁问题如何排查并解决?下面是不同锁等级的区别表级锁:开销小,加锁快;不会出现死锁;锁定粒度...

看懂这篇文章,你就懂了数据库死锁产生的场景和解决方法

一、什么是死锁加锁(Locking)是数据库在并发访问时保证数据一致性和完整性的主要机制。任何事务都需要获得相应对象上的锁才能访问数据,读取数据的事务通常只需要获得读锁(共享锁),修改数据的事务需要获...