Copy and paste
Ctrl+C copies the focused cell or the checked rows for Excel, Ctrl+V pastes a value converted to the column type, and copyable: false keeps columns out.
Live demoCopy & paste
Copy a cell or the checked rows, paste a value from Excel, keep a column out of copies.
Code for this demo
import { createGrid } from '@freegridjs/core';
import { makeRows } from '../data';
import { button, separator, text, tr, type DemoContext } from '../ui';
export default function mount(ctx: DemoContext) {
const { lang } = ctx;
const h = (en: string, ko: string) => tr(lang, { en, ko });
const grid = createGrid(ctx.host, {
columns: [
{ field: 'id', header: 'ID', type: 'number', width: 80 },
{ field: 'name', header: h('Name', '이름'), width: 170, editable: true },
{ field: 'q1', header: h('Q1 revenue', '1분기 매출'), type: 'number', format: '#,##0', width: 130, editable: true },
{ field: 'joined', header: h('Joined', '가입일'), type: 'date', width: 130, editable: true },
// national-id style column: never copied
{ field: 'email', header: h('Email (not copied)', '이메일 (복사 안 됨)'), width: 240, copyable: false, cellClass: 'demo-secret' },
],
data: makeRows(300),
locale: lang,
rowSelection: 'multiple',
rangeSelection: false, // a click focuses one cell
});
grid.on('paste', e => ctx.log(`paste → changed ${e.changed}, skipped ${e.skipped}`));
grid.on('cellValueChanged', e => ctx.log(`cellValueChanged → ${e.colId}: ${String(e.oldValue)} → ${String(e.newValue)}`));
text(ctx, h('Click a cell and press Ctrl+C, then click a Q1 cell and press Ctrl+V. Text like "1,234" or "(50)" becomes a number.',
'셀을 클릭하고 Ctrl+C, 1분기 셀을 클릭하고 Ctrl+V를 눌러 보세요. "1,234"나 "(50)" 같은 글자도 숫자로 바뀝니다.'));
separator(ctx);
button(ctx, h('Copy the checked rows', '체크한 행 복사'), () => {
const tsv = grid.copySelection({ rows: true, headers: true });
ctx.log(h(`copied ${tsv ? tsv.split('\r\n').length : 0} lines`, `${tsv ? tsv.split('\r\n').length : 0}줄 복사됨`));
});
// pasteText goes to the focused cell: click a Q1 cell first
button(ctx, h('Paste "₩12,000" into the focused cell', '포커스 셀에 "₩12,000" 붙여넣기'), () => grid.pasteText('₩12,000'));
button(ctx, h('Undo', '실행 취소'), () => grid.undo());
return grid;
}Ctrl+C (⌘C) copies the focused cell, and Ctrl+V pastes one value into it, from Excel, Google Sheets or any text. Numbers are copied as numbers and dates as YYYY-MM-DD, so they land correctly in a spreadsheet. copySelection({ rows: true }) copies the checked rows as Excel text, one line per row, with a header line when you add headers: true.
Pasting only changes columns that are editable, so ids and computed columns stay safe, and the value is converted to the column type: 1,234, ₩12,000, (5) and 12% become numbers; 2026. 3. 5. and 2026년 3월 5일 become dates; select columns take one of their options. A value that cannot be converted, or that breaks a validation rule, is skipped and counted in the paste event. Pastes can be undone with Ctrl+Z.
const grid = createGrid(el, {
columns: [
{ field: 'id', type: 'number' }, // read-only: pasting does nothing
{ field: 'qty', type: 'number', editable: true }, // "1,234", "₩12,000", "(5)", "12%" become numbers
{ field: 'due', type: 'date', editable: true }, // "2026. 3. 5." and "2026년 3월 5일" become dates
{ field: 'rrn', copyable: false }, // national ids: copied as empty text
],
data,
rowSelection: 'multiple',
rangeSelection: false, // a click focuses one cell
});
grid.copySelection(); // the focused cell (Ctrl+C)
grid.copySelection({ rows: true, headers: true }); // the checked rows, with a header line
grid.pasteText('1,234'); // one value into the focused cell (Ctrl+V)
grid.on('paste', e => console.log(e.changed, e.skipped));Give columns that must not leave the screen, such as national ids, copyable: false: their cells copy as empty text. A function decides per cell.
Browsers let a page write to the clipboard after a key press or click. Ctrl+V always works because it uses the browser's own paste event.
Copying and pasting blocks of cells, from a drag selection or several ranges, is part of Cell ranges and range copy.
Pasting more rows than there are
With pasteAddsRows, pasting more lines than there are rows below adds the rest as new rows. See:
Methods, options and events
| Name | Type | Description |
|---|---|---|
copySelection({ rows?, headers? }) | string | Copy the focused cell, or with rows: true the checked rows, as Excel text (TSV); also writes the clipboard when the browser allows it. |
pasteText(text) | { changed, skipped } | Paste one value into the focused cell. |
copyable | boolean | ({ value, row, column }) => boolean | Column: false keeps values out of copies; blocked cells copy as empty text. |
paste | { changed, skipped } (event) | A paste finished; skipped counts values that could not be converted. |