docs.sheetjs.com/docz/docs/03-demos/08-local/05-clipboard.md

233 lines
7.5 KiB
Markdown
Raw Normal View History

2022-07-06 05:38:24 +00:00
---
2022-08-26 05:39:17 +00:00
title: Clipboard Data
2023-02-28 11:40:44 +00:00
pagination_prev: demos/data/index
pagination_next: demos/cloud/index
sidebar_custom_props:
summary: Reading and writing data and files in the clipboard
2022-07-06 05:38:24 +00:00
---
Spreadsheet software like Excel typically support copying and pasting cells and
2022-08-23 03:20:02 +00:00
data. This is implemented through the Clipboard ("Pasteboard" in MacOS).
2022-07-06 05:38:24 +00:00
When copying a selection of cells, Excel for Windows stores a screenshot of the
selected cells as an image. It also creates and stores a number of strings and
files for the various formats, including TSV, CSV, HTML, RTF, SYLK, DIF, XLSB,
XLS (both '97-2004 and '95), and SpreadsheetML 2003.
Not all Clipboard APIs offer access to all clipboard types.
2022-07-07 04:05:14 +00:00
## Browser Reading (paste)
2022-07-06 05:38:24 +00:00
Clipboard data can be read from a `paste` event, accessible from the event
`clipboardData` property:
```js
document.onpaste = function(e) {
/* get TSV */
var str = e.clipboardData.getData('text/html');
/* parse */
var wb = XLSX.read(str, {type: "string"});
/* DO SOMETHING WITH wb HERE */
2022-07-07 04:05:14 +00:00
};
2022-07-06 05:38:24 +00:00
```
`getData` accepts one argument: the desired MIME type. Chrome 103 supports:
| MIME type | Data format |
|:-------------|:---------------------------|
| `text/plain` | TSV (tab separated values) |
| `text/html` | HTML |
| `text/rtf` | RTF (rich text format) |
`getData` returns a string compatible with the `string` type for `XLSX.read`.
### Live Demo
Open a file in Excel, copy some cells, then come back to this window. Click on
"RESULT" below and paste (Control+V for Windows, Command+V for Mac).
```jsx live
2022-10-18 07:55:41 +00:00
function ClipboardRead() {
2022-07-06 05:38:24 +00:00
const [csvs, setCSVs] = React.useState([ "", "", "" ]);
/* Set up paste handler */
2022-10-18 07:55:41 +00:00
const paste = React.useCallback((e) => {
/* this demo will read 3 different clipboard data types */
var mime_arr = [ 'text/plain', 'text/html', 'text/rtf' ];
/* get clipboard data for each type */
var data_arr = mime_arr.map(mime => e.clipboardData.getData(mime));
/* parse each data string into a workbook */
var wb_arr = data_arr.map(str => XLSX.read(str, {type: "string"}));
/* get first worksheet from each workbook */
var ws_arr = wb_arr.map(wb => wb.Sheets[wb.SheetNames[0]]);
/* generate CSV for each "first worksheet" */
var result = ws_arr.map(ws => XLSX.utils.sheet_to_csv(ws));
setCSVs(result);
2022-07-06 05:38:24 +00:00
}, []);
2022-10-18 07:55:41 +00:00
return ( <>
2022-07-06 05:38:24 +00:00
{csvs[0] && (<pre><b>Data from clipboard TSV (text/plain)</b><br/>{csvs[0]}</pre>)}
{csvs[1] && (<pre><b>Data from clipboard HTML (text/html)</b><br/>{csvs[1]}</pre>)}
{csvs[2] && (<pre><b>Data from clipboard RTF (text/rtf)</b><br/>{csvs[2]}</pre>)}
2022-10-18 07:55:41 +00:00
{csvs.every(x => !x) && <b onPaste={paste}>Copy data in Excel, click here, and paste (Control+V)</b>}
</> );
2022-07-07 04:05:14 +00:00
}
```
2022-10-18 07:55:41 +00:00
### Reading Files
Modern browsers support reading files that users have copied into the clipboard.
:::caution
Excel does not copy data into files! Use your system file browser to select and
copy spreadsheets into the clipboard.
:::
The event `clipboardData.files` property, if it is set, is a list of files.
```jsx live
function ClipboardReadFiles() {
const [data, setData] = React.useState([]);
/* Set up paste handler */
const paste = React.useCallback(async(e)=>{
const result = [];
/* loop over files */
const files = e.clipboardData.files || [];
for(let i = 0; i < files.length; ++i) {
const file = files.item(i);
/* filter MIME type for spreadsheets */
if(!file.type.match(/excel|sheet|csv/)) continue;
/* read data */
const wb = XLSX.read(await file.arrayBuffer());
/* capture sheet names */
result.push([file.name, wb.SheetNames]);
}
setData(result);
}, []);
return ( <>
{data.map((f,idx) => (<pre key={idx}>
<b>Sheet Names from {f[0]}</b><br/>{f[1].join("\n")}
</pre>))}
{!data.length && (<b onPaste={paste}>Copy files, click here, and paste (Control+V)</b>)}
</> );
}
```
2022-07-07 04:05:14 +00:00
## Browser Writing (copy)
Clipboard data can be written from a `copy` event, accessible from the event
`clipboardData` property:
```js
document.oncopy = function(e) {
/* get HTML of first worksheet in workbook */
var str = XLSX.write(wb, {type: "string", bookType: "html"});
/* set HTML clipboard data */
e.clipboardData.setData('text/html', str);
/* prevent the browser from copying the normal data */
e.preventDefault();
};
```
`setData` accepts two arguments: MIME type and new data. Chrome 103 supports:
| MIME type | Data format |
|:-------------|:---------------------------|
| `text/plain` | TSV (tab separated values) |
| `text/html` | HTML |
Browsers do not currently support assigning to the `text/rtf` clipboard type.
### Live Demo
This demo creates a simple workbook from the following HTML table:
2022-10-18 07:55:41 +00:00
<table id="srcdata"><tbody>
2022-07-07 04:05:14 +00:00
<tr><td>SheetJS</td><td>Clipboard</td><td>Demo</td></tr>
<tr><td>bookType</td><td>RTF</td></tr>
<tr><td>source</td><td>HTML Table</td></tr>
2022-10-18 07:55:41 +00:00
</tbody></table>
2022-07-07 04:05:14 +00:00
Create a new file in Excel then come back to this window. Select the text
below and copy (Control+C for Windows, Command+C for Mac). Go back to the
excel
```jsx live
2022-10-18 07:55:41 +00:00
function ClipboardWrite() {
2022-07-07 04:05:14 +00:00
/* Set up copy handler */
2022-10-18 07:55:41 +00:00
const copy = React.useCallback((e) => {
/* generate workbook from table */
var wb = XLSX.utils.table_to_book(document.getElementById("srcdata"));
/* get HTML of first worksheet in workbook */
var str = XLSX.write(wb, {type: "string", bookType: "html"});
/* set HTML clipboard data */
e.clipboardData.setData('text/html', str);
/* prevent the browser from copying the normal data */
e.preventDefault();
2022-07-07 04:05:14 +00:00
}, []);
return (
2022-10-18 07:55:41 +00:00
<b onCopy={copy}>Select this text, copy (Control+C), and paste in Excel</b>
2022-07-07 04:05:14 +00:00
);
2022-07-06 05:38:24 +00:00
}
```
2022-07-20 08:58:29 +00:00
## Electron
2022-11-07 23:23:05 +00:00
Electron Clipboard API supports HTML and RTF clipboards.
2022-07-20 08:58:29 +00:00
There are special methods for specific clipboard types:
| File Type | Read Clipboard Data | Write Clipboard Data |
|:----------|:---------------------|:----------------------|
| RTF | `clipboard.readRTF` | `clipboard.writeRTF` |
| TSV | `clipboard.readText` | `clipboard.writeText` |
| HTML | `clipboard.readHTML` | `clipboard.writeHTML` |
Each method operates on JS strings.
2022-11-07 23:23:05 +00:00
`clipboard.write` can assign to multiple clipboard types:
```js
const { clipboard } = require('electron');
const XLSX = require('xlsx');
function copy_first_sheet_to_clipboard(workbook) {
clipboard.write({
text: XLSX.write(wb, {type: "string", bookType: "txt"}),
rtf: XLSX.write(wb, {type: "string", bookType: "rtf"}),
html: XLSX.write(wb, {type: "string", bookType: "html"})
});
}
```
2022-07-20 08:58:29 +00:00
:::caution Experimental Buffer Clipboard Support
Electron additionally supports binary operations using `Buffer` objects. This
support is considered "experimental" and is not guaranteed to work on any
platform. Issues should be raised with the Electron project
2022-08-23 03:20:02 +00:00
On the `MacOS` platform, some versions of Excel store a packaged file with key
2022-07-20 08:58:29 +00:00
`dyn.ah62d4qmxhk4d425try1g44pdsm11g55gsu1en5pcqzwc4y5tsz3gg3k`. The package is
a simple CFB file that can be parsed:
```js
2022-11-07 23:23:05 +00:00
const { clipboard } = require('electron');
2022-07-20 08:58:29 +00:00
const XLSX = require("xlsx");
const buf = clipboard.readBuffer('dyn.ah62d4qmxhk4d425try1g44pdsm11g55gsu1en5pcqzwc4y5tsz3gg3k');
2022-07-30 22:17:34 +00:00
const cfb = XLSX.CFB.read(buf, {type: "buffer"});
2022-07-20 08:58:29 +00:00
const pkg = XLSX.CFB.find(cfb, "Package").content;
const wb = XLSX.read(pkg);
```
:::