通过JS实现点击复制页面表格到Excel

本文基于react项目实现。

起因

接了一个需求,要求实现点击页面上的一个按钮,复制某个表格数据,然后ctrl+V到Excel表格中。

思考

其实我觉着这个功能用导出Excel的方式实现不就好了么。不过本着好奇的心思,还是试着做做看吧。
首先,点击按钮的时候要拿到要复制的数据。最初是想通过获取DOM元素的方式来取得表格,可是这样的话,得到的就是含有html标签的一堆字符串。那么只能自己来拼装数据了。我把表格部分的数据通过复制、黏贴到编辑器看下他是什么,结果如下图:
《通过JS实现点击复制页面表格到Excel》
而页面上的表格是这样的:
《通过JS实现点击复制页面表格到Excel》
对比来看:跟页面上的表格差别不大。
其次,要把数据组装好之后,要通过JS的方式放到剪切板中。这个有点难度了。通过查资料下面这种方式可以改变剪切板的内容。

 document.addEventListener("copy", (event) => { 
      if (copyEvent) { 
        if (event.clipboardData || event.originalEvent) { 
          var clipboardData = (event.clipboardData || event.originalEvent.clipboardData);
          const selection = "好激动12312412\nhahahha";
          clipboardData.setData('text/plain', selection.toString());
          event.preventDefault();
        }
      }
    });

那么,问题来了,这里是通过监听copy事件来改变剪切板的内容的,但是我们点击按钮到复制到Excel里面,这过程中并没有触发ctrl+C的操作啊?
那么只能点击按钮的时候来触发了。document.execCommand('copy')可以实现。
然后,由于是在document上做的监听,那么页面上所有的复制操作都被拦截了,换成我们拼接的内容啦。显然这不是我们想要的。于是我想到了开关,在点击按钮的时候打开开关,然后触发copy事件,在监听事件中判断开关状态,这样就能过滤掉其他位置的复制的操作了。

实现

• 先准备环境、数据

import {  Button, Table } from 'antd';
import {  useEffect } from 'react'
import './App.css';
const dataSource = [
  { 
    key: '1',
    name: '胡彦斌',
    age: 32,
    address: '西湖区湖底公园1号',
  },
  { 
    key: '2',
    name: '胡彦祖',
    age: 42,
    address: '西湖区湖底公园1号',
  },
];
const columns = [
  { 
    title: '姓名',
    dataIndex: 'name',
    key: 'name',
  },
  { 
    title: '年龄',
    dataIndex: 'age',
    key: 'age',
  },
  { 
    title: '住址',
    dataIndex: 'address',
    key: 'address',
  },
]
const btnClick = () => { 
  
}
function App() { 
  return (
    <div className="App">
      <header className="App-header">
        <Button type="primary" onClick={ btnClick}>复制</Button>
        <Table dataSource={ dataSource} columns={ columns} />
      </header>
    </div>
  );
}
export default App;

• 监听copy事件,点击按钮的时候触发copy事件

const btnClick = () => { 
  document.execCommand('copy')
}
  useEffect(() => { 
    document.addEventListener("copy", (event) => { 
        if (event.clipboardData || event.originalEvent) { 
          var clipboardData = (event.clipboardData || event.originalEvent.clipboardData);
          const selection = "好激动12312412\nhahahha";
          clipboardData.setData('text/plain', selection.toString());
          event.preventDefault();
          copyEvent = false
        }
    });
  }, []);

• 添加开关、拼接数据

let copyEvent = false // 开关
const btnClick = () => { 
  copyEvent = true
  document.execCommand('copy')
}
  useEffect(() => { 
    document.addEventListener("copy", (event) => { 
      if (copyEvent) { 
        if (event.clipboardData || event.originalEvent) { 
          var clipboardData = (event.clipboardData || event.originalEvent.clipboardData);
          // 拼接数据 
          const first = columns.map(item=>item.title).join('\t')
          const sec = dataSource.map(item=> `${ item.name}\t${ item.age} \t${ item.address}`).join('\n')
          const selection = `${ first}\n${ sec}`
          clipboardData.setData('text/plain', selection.toString());
          event.preventDefault();
          copyEvent = false // 关掉开关
        }
      }
    });
  }, []);

\t是制表符,在Excel中就是单元格分隔。\n是换行符,对应Excel就是不同行。
复制到Excel中的效果:
《通过JS实现点击复制页面表格到Excel》

完整代码

import {  Button, Table } from 'antd';
import {  useEffect } from 'react'
import './App.css';
const dataSource = [
  { 
    key: '1',
    name: '胡彦斌',
    age: 32,
    address: '西湖区湖底公园1号',
  },
  { 
    key: '2',
    name: '胡彦祖',
    age: 42,
    address: '西湖区湖底公园1号',
  },
];
const columns = [
  { 
    title: '姓名',
    dataIndex: 'name',
    key: 'name',
  },
  { 
    title: '年龄',
    dataIndex: 'age',
    key: 'age',
  },
  { 
    title: '住址',
    dataIndex: 'address',
    key: 'address',
  },
]
let copyEvent = false // 开关
const btnClick = () => { 
  copyEvent = true
  document.execCommand('copy')
}
function App() { 
  useEffect(() => { 
    document.addEventListener("copy", (event) => { 
      if (copyEvent) { 
        if (event.clipboardData || event.originalEvent) { 
          var clipboardData = (event.clipboardData || event.originalEvent.clipboardData);
          // 拼接数据 
          const first = columns.map(item=>item.title).join('\t')
          const sec = dataSource.map(item=> `${ item.name}\t${ item.age} \t${ item.address}`).join('\n')
          const selection = `${ first}\n${ sec}`
          clipboardData.setData('text/plain', selection.toString());
          event.preventDefault();
          copyEvent = false // 关掉开关
        }
      }
    });
  }, []);
  return (
    <div className="App">
      <header className="App-header">
        <Button type="primary" onClick={ btnClick}>复制</Button>
        <Table dataSource={ dataSource} columns={ columns} />
      </header>
    </div>
  );
}
export default App;

参考

execCommand
JS设置获取剪切板内容

    原文作者:柒月梦
    原文地址: https://blog.csdn.net/guo187/article/details/113701197
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞