Export and import
exportXlsx() saves the rows as a real Excel file. Numbers stay numbers with the column's format, dates stay dates, column groups become merged header…
Live demoExport, import & filters panel
Save to Excel, CSV, JSON or PDF, read Excel or CSV files back in, and filter from a side panel.
Code for this demo
import { createGrid, exportWorkbook, 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 });
const columns: ColumnDef[] = [
{ field: 'id', header: 'ID', type: 'number', width: 80 },
{ field: 'name', header: h('Name', '이름'), width: 160, editable: true, align: 'center' },
{ field: 'country', header: h('Country', '국가'), width: 140, filter: 'set', editable: true },
{ header: h('Revenue', '매출'), children: [
// low values are red; the color and the right alignment also go into the Excel file
{ field: 'q1', header: h('Q1', '1분기'), type: 'number', format: '#,##0', width: 110, editable: true,
cellClass: ({ value }) => (Number(value) < 20000 ? 'demo-low' : undefined) },
{ field: 'q2', header: h('Q2', '2분기'), type: 'number', format: '#,##0', width: 110, editable: true },
] },
{ field: 'growth', header: h('Growth', '성장률'), type: 'number', format: '0.0%', width: 100 },
{ field: 'joined', header: h('Joined', '가입일'), type: 'date', width: 120, editable: true },
{ field: 'active', header: h('Active', '활성'), type: 'boolean', width: 80, editable: true },
];
const grid = createGrid(ctx.host, {
columns,
data: makeRows(300),
locale: lang,
theme: 'classic',
rowSelection: 'multiple',
sideBar: { open: true, panels: ['filters', 'columns'] },
});
grid.on('filterChange', e => ctx.log(`filterChange → ${Object.keys(e.filters).join(', ') || h('none', '없음')}`));
text(ctx, h('Filter on the right, then export only what you see. Right-click a cell for the same commands.',
'오른쪽 필터 패널로 걸러 낸 뒤 보이는 행만 내보내 보세요. 셀을 우클릭해도 같은 메뉴가 나옵니다.'));
separator(ctx);
button(ctx, h('Export Excel', '엑셀로 내보내기'), () => grid.exportXlsx(h('freegrid-demo.xlsx', 'freegrid-데모.xlsx')));
button(ctx, h('Export Excel without styles', '스타일 없이 엑셀로'), () => grid.exportXlsx('plain.xlsx', { styles: false }));
button(ctx, h('Print', '인쇄'), () => grid.print({
title: h('People', '사람 목록'),
subtitle: h('Current sort and filters', '지금 정렬·필터 그대로'),
footer: 'FreeGrid demo',
}));
// one file, two sheets: the filtered view and the checked rows
button(ctx, h('Excel with two sheets', '시트 두 개짜리 엑셀'), () => exportWorkbook(h('two-sheets.xlsx', '시트2개.xlsx'), [
{ grid, sheetName: h('Filtered', '필터 결과') },
{ grid, sheetName: h('Checked', '체크한 행'), options: { rows: 'selected' } },
]));
button(ctx, h('Export CSV', 'CSV로 내보내기'), () => grid.exportCsv(h('freegrid-demo.csv', 'freegrid-데모.csv')));
button(ctx, h('Export checked rows', '체크한 행만 내보내기'), () => grid.exportXlsx('selected.xlsx', { rows: 'selected' }));
separator(ctx);
// Import: a hidden file input behind a normal button
const input = document.createElement('input');
input.type = 'file';
input.accept = '.xlsx,.csv,.tsv,.txt';
input.hidden = true;
input.addEventListener('change', async () => {
const file = input.files?.[0];
input.value = '';
if (!file) return;
try {
const res = await grid.importFile(file, { mode: 'append' });
ctx.log(h(`imported ${res.rows.length} rows (${res.skipped} cells skipped) — Ctrl+Z undoes it`,
`${res.rows.length}행을 가져왔습니다 (건너뛴 셀 ${res.skipped}개) — Ctrl+Z로 되돌릴 수 있습니다`));
grid.scrollToRow(grid.getDisplayedRowCount() - 1);
} catch (e) {
ctx.log(`import failed: ${(e as Error).message}`);
}
});
ctx.controls.append(input);
button(ctx, h('Import Excel / CSV…', '엑셀·CSV 가져오기…'), () => input.click());
return grid;
}exportXlsx() saves the rows as a real Excel file. Numbers stay numbers with the column's format, dates stay dates, column groups become merged header rows, and the header is frozen with filter buttons. exportCsv() writes CSV with a byte order mark, so Excel opens Korean and other non-Latin text correctly. Text that looks like a formula is prefixed so a spreadsheet never runs it. Both export what is on screen by default: the current sort and filters, and the visible columns. Choose other rows or columns with the options.
importFile() reads an .xlsx or CSV file. The first row is matched to your columns by header or field name, and every value is checked like a paste, so a number column only takes numbers and a date column takes dates such as 2026-03-05 or 2026.3.5. Imported rows are added at the end and can be undone, or they can replace the data. With sideBar, people get a Filters panel next to the Columns panel and can filter several columns at once.
Excel files carry the column align and the text color, background and bold that cellClass gives. Pass styles: false to leave them out.
// Download what people see (current sort and filters)
grid.exportXlsx('orders.xlsx');
grid.exportCsv('orders.csv', { separator: ';' });
// Pick columns and rows
grid.exportXlsx('picked.xlsx', { columns: ['name', 'total'], rows: 'selected', sheetName: 'Picked' });
// Read a file chosen by the user
input.addEventListener('change', async () => {
const { rows, skipped } = await grid.importFile(input.files[0]); // { mode: 'replace' } to swap
});
// Filters in a side panel next to the columns panel
createGrid(el, { columns, data, sideBar: { open: true, panels: ['filters', 'columns'] } });
// Without a grid
import { writeXlsx, readXlsx } from '@freegridjs/core';
const bytes = writeXlsx([{ name: 'Report', rows: [['Name', 'Total'], ['Kim', 1200]] }]);JSON and PDF
exportJson() saves the rows as an array of objects keyed by column id (or header). Numbers, booleans and blanks keep their types, formulas give their results, and formatted: true saves the text as shown. For PDF see Print and PDF. exportWorkbook() puts several grids into one Excel file, a sheet each.
grid.exportJson('orders.json'); // the rows and columns on screen
grid.exportJson('orders.json', { keys: 'header', rows: 'selected' });
const text = grid.getJson({ columns: ['id', 'amount'], space: 0 }); // [{"id":1,"amount":32000},…]
grid.exportPdf('orders.pdf', { title: 'Orders' });
// several grids in one Excel file
exportWorkbook('report.xlsx', [{ grid: orders, sheetName: 'Orders' }, { grid: items, sheetName: 'Items' }]);Questions about this page
Can FreeGrid export to Excel, CSV and JSON?
Yes: exportXlsx writes a real .xlsx file with formats, merged headers and colours, exportCsv writes UTF-8 CSV that opens in Excel, and exportJson writes an array of row objects.
Can users import Excel files into the grid?
Yes. importFile reads .xlsx and CSV files, matches columns by header or field, and checks values the same way as pasting.