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;
相关推荐
大橙子额44 分钟前
【解决报错】Cannot assign to read only property ‘exports‘ of object ‘#<Object>‘
前端·javascript·vue.js
WooaiJava2 小时前
AI 智能助手项目面试技术要点总结(前端部分)
javascript·大模型·html5
LYFlied2 小时前
从 Vue 到 React,再到 React Native:资深前端开发者的平滑过渡指南
vue.js·react native·react.js
Never_Satisfied2 小时前
在JavaScript / HTML中,关于querySelectorAll方法
开发语言·javascript·html
董世昌412 小时前
深度解析ES6 Set与Map:相同点、核心差异及实战选型
前端·javascript·es6
WeiXiao_Hyy3 小时前
成为 Top 1% 的工程师
java·开发语言·javascript·经验分享·后端
xjt_09014 小时前
基于 Vue 3 构建企业级 Web Components 组件库
前端·javascript·vue.js
我是伪码农4 小时前
Vue 2.3
前端·javascript·vue.js
辰风沐阳4 小时前
JavaScript 的宏任务和微任务
javascript
冰暮流星5 小时前
javascript之二重循环练习
开发语言·javascript·数据库