React(五):XLS、XLSX文件在线预览

效果

依赖

bash 复制代码
$ yarn add xlsx

源码

css 复制代码
.xlsx-wrap {
  position: relative;
  width: 100%;
  height: 100%;
  background-color: #fafafa;

  .ant-tabs {
    width: 100%;
    height: 100%;

    .ant-tabs-nav {
      height: 50px;
      padding: 0 10px;
      margin-bottom: 0;
    }

    .ant-tabs-content-holder {
      border-top: 1px solid #000000;
      height: calc(100% - 50px);

      .ant-tabs-content {
        height: 100%;

        .ant-tabs-tabpane {
          height: 100%;

          .table-container {
            width: 100%;
            height: 100%;
            padding: 10px;
            overflow: auto;

            table {
              border-top: 1px solid red;
              border-left: 1px solid red;
              border-collapse: collapse;

              td {
                border-bottom: 1px solid red;
                border-right: 1px solid red;
                padding: 5px 10px;
              }
            }
          }
        }
      }
    }
  }
}
js 复制代码
import './index.scss';
import {useCallback, useMemo, useRef, useState} from 'react';
import type {UploadRequestOption} from 'rc-upload/lib/interface';
import {Button, Flex, Tabs, Upload} from 'antd';
import {read, utils, WorkBook, writeFileXLSX} from 'xlsx';

function PreviewXLSX() {
    const tableContainerRef = useRef<HTMLDivElement>(null);

    const [workBook, setWorkBook] = useState<WorkBook>({
        SheetNames: [],
        Sheets: {},
    });

    const items = workBook.SheetNames
        .map((d, i) => ({
            key: `${i}`,
            label: d,
            children: <div className="table-container" ref={tableContainerRef} dangerouslySetInnerHTML={{__html: utils.sheet_to_html(workBook.Sheets[d])}}/>
        }));

    const fileUpload = async (options: UploadRequestOption) => {
        const fileReader = new FileReader();
        fileReader.readAsArrayBuffer(options.file as File);
        fileReader.onload = e => {
            const buffer = e.target!.result;
            console.log(read(buffer));
            setWorkBook({...workBook, ...read(buffer)});
        };
    };

    const exportFile = useCallback(() => {
        const table = tableContainerRef.current!.getElementsByTagName('TABLE')[0];
        const wb = utils.table_to_book(table);
        writeFileXLSX(wb, 'table_to_xlsx.xlsx');
    }, [tableContainerRef]);

    return (<>
        <div className="xlsx-wrap">
            <Tabs tabBarExtraContent={
                <Flex justify="flex-end" align="center" gap={10}>
                    <Button onClick={exportFile}>导出</Button>
                    <Upload action="#" customRequest={fileUpload} showUploadList={false}>
                        <Button type="primary">点击上传</Button>
                    </Upload>
                </Flex>
            } items={useMemo(() => items, [items])}/>
        </div>
    </>);
}

export default PreviewXLSX;
相关推荐
吃饭睡觉打豆豆嘛1 小时前
深入剖析 Promise 实现:从原理到手写完整实现
前端·javascript
Spider_Man1 小时前
从 “不会迭代” 到 “面试加分”:JS 迭代器现场教学
前端·javascript·面试
小高0071 小时前
🧙‍♂️ 老司机私藏清单:从“记事本”到“旗舰 IDE”,我只装了这 12 个插件
前端·javascript·vue.js
EveryPossible2 小时前
终止异步操作
前端·javascript·vue.js
Stringzhua2 小时前
setup函数相关【3】
前端·javascript·vue.js
neon12042 小时前
解决Vue Canvas组件在高DPR屏幕上的绘制偏移和区域缩放问题
前端·javascript·vue.js·canva可画
Sammyyyyy2 小时前
Node.js 做 Web 后端优势为什么这么大?
开发语言·前端·javascript·后端·node.js·servbay
Bling_Bling_13 小时前
面试常考:js中 Map和 Object 的区别
开发语言·前端·javascript
前端小巷子4 小时前
JS实现丝滑文字滚动
前端·javascript·面试
写不出来就跑路4 小时前
基于 HTML+CSS+JavaScript 的薪资实时计算器(含本地存储和炫酷动画)
javascript·css·html