Preview Updated 2026-05-10

Spreadsheet

A1-style editable grid — multi-select, keyboard navigation (arrows / Tab / Enter / F2 / Delete), Cmd+C/V clipboard interop.

Basic usage

v-model binds a flat Record<string, string> keyed by A1 strings. You get an editable grid where:

  • Click a cell → select
  • Drag / Shift+click → range selection
  • Double-click / Enter / F2 → edit
  • Arrow keys / Tab → move the focus
  • Delete / Backspace → clear the selection
  • Cmd/Ctrl + C / X / V → TSV roundtrip with the system clipboard
背景

单击选中、双击编辑、方向键移动、Tab/Enter 确认;Cmd/Ctrl + C / V 在选区与剪贴板间复制粘贴 TSV。

A1A1
A
B
C
D
E
1
产品
区域
销量
2
A
华北
120
3
B
华东
230
4
C
华南
180
5
6
7
8
9
10
src/App.vue
<script setup lang="ts">
import { ref } from 'vue';
import { CfSpreadsheet } from '@chufix-design/vue';

const data = ref<Record<string, string>>({
  A1: '产品',
  B1: '区域',
  C1: '销量',
  A2: 'A',
  B2: '华北',
  C2: '120',
  A3: 'B',
  B3: '华东',
  C3: '230',
  A4: 'C',
  B4: '华南',
  C4: '180',
});
</script>
<template>
  <p style="margin: 0 0 8px; color: var(--fg-3); font-size: 12px;">
    单击选中、双击编辑、方向键移动、Tab/Enter 确认;Cmd/Ctrl + C / V 在选区与剪贴板间复制粘贴 TSV。
  </p>
  <CfSpreadsheet v-model="data" :rows="10" :cols="5" />
</template>
<script setup>
import { ref } from 'vue';
import { CfSpreadsheet } from '@chufix-design/vue';

const data = ref<Record<string, string>>({
  A1: '产品',
  B1: '区域',
  C1: '销量',
  A2: 'A',
  B2: '华北',
  C2: '120',
  A3: 'B',
  B3: '华东',
  C3: '230',
  A4: 'C',
  B4: '华南',
  C4: '180',
});
</script>
<template>
  <p style="margin: 0 0 8px; color: var(--fg-3); font-size: 12px;">
    单击选中、双击编辑、方向键移动、Tab/Enter 确认;Cmd/Ctrl + C / V 在选区与剪贴板间复制粘贴 TSV。
  </p>
  <CfSpreadsheet v-model="data" :rows="10" :cols="5" />
</template>

External roundtrip

The clipboard format is plain TSV (tab-separated text), so you can copy/paste directly between this grid and Excel / Numbers / Google Sheets:

背景
A1A1
A
B
C
D
E
1
2
3
4
5
6
7
8
9
10

试试:在 Excel / Numbers / Sheets 选一段复制,到这里 Cmd/Ctrl+V 粘贴;反向 Cmd/Ctrl+C 也能拷出去。

src/App.vue
<script setup lang="ts">
import { ref } from 'vue';
import { CfSpreadsheet, CfButton, toast, rangeToTSV } from '@chufix-design/vue';

const data = ref<Record<string, string>>({});

function loadSample() {
  data.value = {
    A1: 'date', B1: 'cpu', C1: 'mem',
    A2: '2026-05-01', B2: '0.42', C2: '0.61',
    A3: '2026-05-02', B3: '0.51', C3: '0.65',
    A4: '2026-05-03', B4: '0.66', C4: '0.72',
    A5: '2026-05-04', B5: '0.49', C5: '0.69',
    A6: '2026-05-05', B6: '0.58', C6: '0.71',
  };
}

async function exportAll() {
  const tsv = rangeToTSV(data.value, {
    start: { col: 0, row: 0 },
    end: { col: 4, row: 9 },
  });
  await navigator.clipboard.writeText(tsv);
  toast({ type: 'success', message: 'TSV 已复制到剪贴板' });
}
</script>
<template>
  <div style="display: flex; gap: 8px; margin-bottom: 8px;">
    <CfButton size="sm" @click="loadSample">载入样例数据</CfButton>
    <CfButton size="sm" variant="tertiary" @click="exportAll">导出全部为 TSV</CfButton>
  </div>
  <CfSpreadsheet v-model="data" :rows="10" :cols="5" :col-width="140" />
  <p style="margin-top: 8px; color: var(--fg-3); font-size: 12px;">
    试试:在 Excel / Numbers / Sheets 选一段复制,到这里 Cmd/Ctrl+V 粘贴;反向 Cmd/Ctrl+C 也能拷出去。
  </p>
</template>
<script setup>
import { ref } from 'vue';
import { CfSpreadsheet, CfButton, toast, rangeToTSV } from '@chufix-design/vue';

const data = ref<Record<string, string>>({});

function loadSample() {
  data.value = {
    A1: 'date', B1: 'cpu', C1: 'mem',
    A2: '2026-05-01', B2: '0.42', C2: '0.61',
    A3: '2026-05-02', B3: '0.51', C3: '0.65',
    A4: '2026-05-03', B4: '0.66', C4: '0.72',
    A5: '2026-05-04', B5: '0.49', C5: '0.69',
    A6: '2026-05-05', B6: '0.58', C6: '0.71',
  };
}

async function exportAll() {
  const tsv = rangeToTSV(data.value, {
    start: { col: 0, row: 0 },
    end: { col: 4, row: 9 },
  });
  await navigator.clipboard.writeText(tsv);
  toast({ type: 'success', message: 'TSV 已复制到剪贴板' });
}
</script>
<template>
  <div style="display: flex; gap: 8px; margin-bottom: 8px;">
    <CfButton size="sm" @click="loadSample">载入样例数据</CfButton>
    <CfButton size="sm" variant="tertiary" @click="exportAll">导出全部为 TSV</CfButton>
  </div>
  <CfSpreadsheet v-model="data" :rows="10" :cols="5" :col-width="140" />
  <p style="margin-top: 8px; color: var(--fg-3); font-size: 12px;">
    试试:在 Excel / Numbers / Sheets 选一段复制,到这里 Cmd/Ctrl+V 粘贴;反向 Cmd/Ctrl+C 也能拷出去。
  </p>
</template>

API

PropTypeDefaultDescription
modelValue (Vue) / modelValue + onChange (React)Record<string, string>{}A1 → value map
rowsnumber20Row count
colsnumber10Column count
colWidthnumber120Pixel column width
rowHeightnumber28Pixel row height
rowHeaderWidthnumber44Row-number header width
readonlybooleanfalseDisable edit / delete / paste
disableClipboardbooleanfalseDisable system-clipboard bridging
captionstringCaption above the sheet
size'sm' | 'md' | 'lg''md'Font size scale

Events:

  • Vue: @update:modelValue(next) / @cell-change({ cell, value }) / @selection-change(range)
  • React: onChange / onCellChange / onSelectionChange

Utilities

import { toA1, colLetter, rangeToTSV, tsvToData } from '@chufix-design/vue';

toA1(0, 0);        // 'A1'
colLetter(27);     // 'AB'
rangeToTSV(data, { start: { col: 0, row: 0 }, end: { col: 2, row: 4 } });
tsvToData('1\t2\n3\t4', { col: 0, row: 0 }, { cols: 10, rows: 20 });

These are pure functions you can use independently of the component.

Keyboard map

KeyAction
← / → / ↑ / ↓Move the focus (hold Shift to extend the selection)
Tab / Shift+TabHorizontal navigation
Enter / F2Edit current cell; while editing, Enter commits and moves down
EscCancel an in-flight edit
Delete / BackspaceClear all cells in the selection
Any printable keyStart editing immediately, seeded with that character
Cmd/Ctrl + C / X / VClipboard TSV bridge
Cmd/Ctrl + ASelect all

反馈与讨论

Spreadsheet · Discussion

0
0 / 600
一键发送
正在加载评论...