Skip to content

Copy, Cut & Paste

WitTable’s ClipboardManager provides full clipboard support. Selected cells can be copied (Ctrl+C), cut (Ctrl+X), or pasted (Ctrl+V). Data is written in two formats simultaneously: text/plain as tab-separated values (TSV) and text/html as an HTML table. This dual-format approach enables seamless interop with Excel and Google Sheets.

Live Demo
Select cells, copy (Ctrl+C), cut (Ctrl+X), click another cell, paste (Ctrl+V). Changes appear in the log below.
Select cells and use Ctrl+C / Ctrl+X / Ctrl+V
View source code
ClipboardDemo.tsx
import { useState } from 'react';
import { WitTable } from '@witqq/spreadsheet-react';
import type { CellChangeEvent } from '@witqq/spreadsheet';
import { DemoWrapper } from './DemoWrapper';
import { generateEmployees, employeeColumns } from './generate-data';
import { useSiteTheme } from './useSiteTheme';
const data = generateEmployees(50);
export function ClipboardDemo() {
const { witTheme } = useSiteTheme();
const [log, setLog] = useState<string[]>(['Select cells and use Ctrl+C / Ctrl+X / Ctrl+V']);
const handleCellChange = (event: CellChangeEvent) => {
setLog(prev => [
`Cell (${event.row}, ${event.col}) → "${event.value}"`,
...prev.slice(0, 9),
]);
};
return (
<DemoWrapper title="Live Demo" description="Select cells, copy (Ctrl+C), cut (Ctrl+X), click another cell, paste (Ctrl+V). Changes appear in the log below." height={440}>
<div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
<div style={{ flex: 1 }}>
<WitTable
theme={witTheme}
columns={employeeColumns}
data={data}
showRowNumbers
editable
onCellChange={handleCellChange}
style={{ width: '100%', height: '100%' }}
/>
</div>
<div style={{ padding: '0.5rem 0.75rem', fontSize: '0.75rem', color: '#64748b', borderTop: '1px solid #e2e8f0', flexShrink: 0, maxHeight: 60, overflow: 'auto' }}>
{log.map((entry, i) => <div key={i}>{entry}</div>)}
</div>
</div>
</DemoWrapper>
);
}

Cut operations clear the source cells using an undoable BatchCellEditCommand, so Ctrl+Z restores the original values. Paste clips at grid boundaries — if the pasted data exceeds the grid dimensions, excess rows and columns are silently dropped.

Clipboard works automatically on any editable table. No additional configuration is needed:

import { WitTable } from '@witqq/spreadsheet-react';
function App() {
return (
<WitTable
columns={columns}
data={data}
editable={true}
/>
);
}

Select a range, press Ctrl+C to copy, click a destination cell, and press Ctrl+V to paste.

<WitTable
columns={columns}
data={data}
editable={true}
onClipboardCopy={(cells) => {
console.log('Copied', cells.length, 'cells');
}}
onClipboardCut={(cells) => {
console.log('Cut', cells.length, 'cells');
}}
onClipboardPaste={(cells, target) => {
console.log('Pasted at', target.row, target.col);
}}
/>
FormatMIME TypeContent
TSVtext/plainTab-separated values, newlines between rows
HTMLtext/html<table> with <tr> and <td> elements

When pasting from external sources, WitTable reads text/plain (TSV) first. If unavailable, it falls back to parsing text/html.

The clipboard module exports standalone serialization functions:

import { serializeToTSV, serializeToHTML, parseTSV, parseHTML } from '@witqq/spreadsheet';
// Serialize cell data to clipboard formats
const tsv: string = serializeToTSV(cells); // Tab-separated values
const html: string = serializeToHTML(cells); // HTML <table>
// Parse clipboard data back to cell values
const fromTSV: CellValue[][] = parseTSV(tsvString);
const fromHTML: CellValue[][] = parseHTML(htmlString);