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;
相关推荐
bin91533 小时前
DeepSeek 助力 Vue 开发:打造丝滑的复制到剪贴板(Copy to Clipboard)
前端·javascript·vue.js·ecmascript·deepseek
晴空万里藏片云4 小时前
elment Table多级表头固定列后,合计行错位显示问题解决
前端·javascript·vue.js
奶球不是球4 小时前
el-button按钮的loading状态设置
前端·javascript
无责任此方_修行中6 小时前
每周见闻分享:杂谈AI取代程序员
javascript·资讯
dorabighead7 小时前
JavaScript 高级程序设计 读书笔记(第三章)
开发语言·javascript·ecmascript
林的快手9 小时前
CSS列表属性
前端·javascript·css·ajax·firefox·html5·safari
bug总结9 小时前
新学一个JavaScript 的 classList API
开发语言·javascript·ecmascript
网络安全-老纪10 小时前
网络安全-js安全知识点与XSS常用payloads
javascript·安全·web安全
yqcoder10 小时前
Express + MongoDB 实现在筛选时间段中用户名的模糊查询
java·前端·javascript
十八朵郁金香10 小时前
通俗易懂的DOM1级标准介绍
开发语言·前端·javascript