스프레드시트 기능
컬럼에 merge: true를 주면 같은 값이 이어지는 행이 한 칸으로 합쳐집니다. 지역별, 팀별 보고서에 유용하며, 먼저 그 컬럼으로 정렬해 두세요. statusBar: true를 켜면 하단에 행 수와 선택한 셀의 개수, 합계, 평균, 최소, 최대가 표시됩니다. 선택 영역…
실행 예제스프레드시트 기능
셀 병합, 채우기 핸들, 합계 상태 표시줄, 고정 행, Ctrl+F 찾기.
이 데모의 코드
import { createGrid, type ColumnDef } 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 });
// Sorted by country so identical countries sit together and merge into one tall cell.
const data = makeRows(400).sort((a, b) => a.country.localeCompare(b.country) || a.company.localeCompare(b.company));
const money = { type: 'number', format: '#,##0', width: 110, editable: true } as const;
const columns: ColumnDef[] = [
{ field: 'country', header: h('Country', '국가'), width: 140, pinned: 'left', merge: true },
{ field: 'company', header: h('Company', '회사'), width: 140, merge: true },
{ field: 'name', header: h('Name', '이름'), width: 160, editable: true },
{ field: 'q1', header: h('Q1 revenue', '1분기 매출'), ...money, wrapHeaderText: true },
{ field: 'q2', header: h('Q2 revenue', '2분기 매출'), ...money, wrapHeaderText: true },
{ field: 'q3', header: h('Q3 revenue', '3분기 매출'), ...money, wrapHeaderText: true },
{ field: 'q4', header: h('Q4 revenue', '4분기 매출'), ...money, wrapHeaderText: true },
{ field: 'joined', header: h('Joined', '가입일'), type: 'date', width: 120, editable: true },
];
const grid = createGrid(ctx.host, {
columns,
data,
locale: lang,
theme: 'erp',
statusBar: true, // counts and totals of the selected cells
fillHandle: true, // drag the blue corner to fill
pinnedTopRows: [{ country: h('Target', '목표'), name: '—', q1: 50000, q2: 55000, q3: 60000, q4: 65000 }],
});
grid.on('cellValueChanged', e => ctx.log(`cellValueChanged → ${e.colId}: ${String(e.oldValue)} → ${String(e.newValue)}`));
text(ctx, h('Drag across Q1–Q4 cells to see totals below. Pull the blue corner down to fill. Ctrl+F finds.',
'1~4분기 셀을 드래그하면 아래에 합계가 나옵니다. 파란 모서리를 끌어내려 채워 보세요. Ctrl+F로 찾기.'));
separator(ctx);
button(ctx, h('Find "Granite"', '"Granite" 찾기'), () => ctx.log(`find → ${grid.find('Granite')} matches`));
button(ctx, h('Next match', '다음 찾기'), () => grid.findNext());
button(ctx, h('Clear find', '찾기 지우기'), () => grid.clearFind());
button(ctx, h('Fill Q1 of the first 10 rows with a series', '첫 10행 1분기를 연속값으로 채우기'), () => {
grid.setRange({ start: { rowIndex: 0, colId: 'q1' }, end: { rowIndex: 0, colId: 'q1' } });
grid.pasteText('1000\n2000');
grid.setRange({ start: { rowIndex: 0, colId: 'q1' }, end: { rowIndex: 1, colId: 'q1' } });
grid.fillRange({ start: { rowIndex: 0, colId: 'q1' }, end: { rowIndex: 9, colId: 'q1' } });
});
button(ctx, h('Undo', '실행 취소'), () => grid.undo());
return grid;
}컬럼에 merge: true를 주면 같은 값이 이어지는 행이 한 칸으로 합쳐집니다. 지역별, 팀별 보고서에 유용하며, 먼저 그 컬럼으로 정렬해 두세요. statusBar: true를 켜면 하단에 행 수와 선택한 셀의 개수, 합계, 평균, 최소, 최대가 표시됩니다. 선택 영역 모서리의 작은 사각형을 끌면 편집 가능한 셀이 채워집니다. 숫자와 날짜는 간격을 이어가고, 숫자로 끝나는 글자는 숫자가 하나씩 늘어나며, 나머지는 반복됩니다.
목표치나 기준값처럼 스크롤해도 계속 보여야 하는 행은 pinnedTopRows, pinnedBottomRows로 고정하세요. Ctrl+F를 누르면 그리드 안에 찾기 창이 열리고, 코드에서는 find()로 같은 일을 할 수 있습니다.
createGrid(el, {
columns: [
{ field: 'region', merge: true }, // identical neighbours become one tall cell
{ field: 'team', merge: (a, b, ra, rb) => a === b && ra.region === rb.region },
{ field: 'q1', type: 'number', editable: true, wrapHeaderText: true },
],
data: rowsSortedByRegion,
statusBar: true, // "1,000 rows · Count 12 Sum 48,000 Average 4,000 …"
fillHandle: true, // drag the corner: 1, 2 → 3, 4, 5 …; Mon → copies; "item 7" → "item 8"
pinnedTopRows: [{ region: 'Target', q1: 50000 }],
});
grid.find('Seoul'); // highlights matches, focuses the first; Ctrl+F opens the same as a bar
grid.findNext();