Export to CSV
Export your grid’s raw data to the CSV format, as a downloadable file, a blob, or a string. Customize your export using Handsontable’s configuration options.
Examples
Mind that CSV exports contain only raw data, and don’t include formulas, styling, or formatting information.
Export to file
import { useRef } from 'react';import { HotTable } from '@handsontable/react-wrapper';import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modulesregisterAllModules();
const ExampleComponent = () => { const hotRef = useRef(null); const buttonClickCallback = () => { const hot = hotRef.current?.hotInstance; const exportPlugin = hot?.getPlugin('exportFile');
exportPlugin?.downloadFile('csv', { bom: false, columnDelimiter: ',', columnHeaders: false, exportHiddenColumns: true, exportHiddenRows: true, fileExtension: 'csv', filename: 'Handsontable-CSV-file_[YYYY]-[MM]-[DD]', mimeType: 'text/csv', rowDelimiter: '\r\n', rowHeaders: true, }); };
return ( <> <div className="example-controls-container"> <div className="controls"> <button id="export-file" onClick={() => buttonClickCallback()}> Download CSV </button> </div> </div> <HotTable ref={hotRef} data={[ ['A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1'], ['A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2'], ['A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3'], ['A4', 'B4', 'C4', 'D4', 'E4', 'F4', 'G4'], ['A5', 'B5', 'C5', 'D5', 'E5', 'F5', 'G5'], ['A6', 'B6', 'C6', 'D6', 'E6', 'F6', 'G6'], ['A7', 'B7', 'C7', 'D7', 'E7', 'F7', 'G7'], ]} colHeaders={true} rowHeaders={true} hiddenRows={{ rows: [1, 3, 5], indicators: true }} hiddenColumns={{ columns: [1, 3, 5], indicators: true }} height="auto" autoWrapRow={true} autoWrapCol={true} licenseKey="non-commercial-and-evaluation" /> </> );};
export default ExampleComponent;import { useRef } from 'react';import { HotTable, HotTableRef } from '@handsontable/react-wrapper';import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modulesregisterAllModules();
const ExampleComponent = () => { const hotRef = useRef<HotTableRef>(null);
const buttonClickCallback = () => { const hot = hotRef.current?.hotInstance; const exportPlugin = hot?.getPlugin('exportFile');
exportPlugin?.downloadFile('csv', { bom: false, columnDelimiter: ',', columnHeaders: false, exportHiddenColumns: true, exportHiddenRows: true, fileExtension: 'csv', filename: 'Handsontable-CSV-file_[YYYY]-[MM]-[DD]', mimeType: 'text/csv', rowDelimiter: '\r\n', rowHeaders: true, }); };
return ( <> <div className="example-controls-container"> <div className="controls"> <button id="export-file" onClick={() => buttonClickCallback()}> Download CSV </button> </div> </div> <HotTable ref={hotRef} data={[ ['A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1'], ['A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2'], ['A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3'], ['A4', 'B4', 'C4', 'D4', 'E4', 'F4', 'G4'], ['A5', 'B5', 'C5', 'D5', 'E5', 'F5', 'G5'], ['A6', 'B6', 'C6', 'D6', 'E6', 'F6', 'G6'], ['A7', 'B7', 'C7', 'D7', 'E7', 'F7', 'G7'], ]} colHeaders={true} rowHeaders={true} hiddenRows={{ rows: [1, 3, 5], indicators: true }} hiddenColumns={{ columns: [1, 3, 5], indicators: true }} height="auto" autoWrapRow={true} autoWrapCol={true} licenseKey="non-commercial-and-evaluation" /> </> );};
export default ExampleComponent;Export as a JavaScript Blob object
Open a console in browser developer tools to see the result for the below example.
import { useRef } from 'react';import { HotTable } from '@handsontable/react-wrapper';import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modulesregisterAllModules();
const ExampleComponent = () => { const hotRef = useRef(null); const buttonClickCallback = () => { const hot = hotRef.current?.hotInstance; const exportPlugin = hot?.getPlugin('exportFile'); const exportedBlob = exportPlugin?.exportAsBlob('csv', { bom: false, columnDelimiter: ',', columnHeaders: false, exportHiddenColumns: true, exportHiddenRows: true, mimeType: 'text/csv', rowDelimiter: '\r\n', rowHeaders: true, });
console.log(exportedBlob); };
return ( <> <div className="controls"> <button id="export-blob" onClick={() => buttonClickCallback()}> Export as a Blob </button> </div> <HotTable ref={hotRef} data={[ ['A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1'], ['A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2'], ['A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3'], ['A4', 'B4', 'C4', 'D4', 'E4', 'F4', 'G4'], ['A5', 'B5', 'C5', 'D5', 'E5', 'F5', 'G5'], ['A6', 'B6', 'C6', 'D6', 'E6', 'F6', 'G6'], ['A7', 'B7', 'C7', 'D7', 'E7', 'F7', 'G7'], ]} colHeaders={true} rowHeaders={true} hiddenRows={{ rows: [1, 3, 5], indicators: true }} hiddenColumns={{ columns: [1, 3, 5], indicators: true }} height="auto" autoWrapRow={true} autoWrapCol={true} licenseKey="non-commercial-and-evaluation" /> </> );};
export default ExampleComponent;import { useRef } from 'react';import { HotTable, HotTableRef } from '@handsontable/react-wrapper';import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modulesregisterAllModules();
const ExampleComponent = () => { const hotRef = useRef<HotTableRef>(null);
const buttonClickCallback = () => { const hot = hotRef.current?.hotInstance; const exportPlugin = hot?.getPlugin('exportFile'); const exportedBlob = exportPlugin?.exportAsBlob('csv', { bom: false, columnDelimiter: ',', columnHeaders: false, exportHiddenColumns: true, exportHiddenRows: true, mimeType: 'text/csv', rowDelimiter: '\r\n', rowHeaders: true, });
console.log(exportedBlob); };
return ( <> <div className="controls"> <button id="export-blob" onClick={() => buttonClickCallback()}> Export as a Blob </button> </div> <HotTable ref={hotRef} data={[ ['A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1'], ['A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2'], ['A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3'], ['A4', 'B4', 'C4', 'D4', 'E4', 'F4', 'G4'], ['A5', 'B5', 'C5', 'D5', 'E5', 'F5', 'G5'], ['A6', 'B6', 'C6', 'D6', 'E6', 'F6', 'G6'], ['A7', 'B7', 'C7', 'D7', 'E7', 'F7', 'G7'], ]} colHeaders={true} rowHeaders={true} hiddenRows={{ rows: [1, 3, 5], indicators: true }} hiddenColumns={{ columns: [1, 3, 5], indicators: true }} height="auto" autoWrapRow={true} autoWrapCol={true} licenseKey="non-commercial-and-evaluation" /> </> );};
export default ExampleComponent;Export as a string
Open a console in browser developer tools to see the result for the below example.
import { useRef } from 'react';import { HotTable } from '@handsontable/react-wrapper';import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modulesregisterAllModules();
const ExampleComponent = () => { const hotRef = useRef(null); const buttonClickCallback = () => { const hot = hotRef.current?.hotInstance; const exportPlugin = hot?.getPlugin('exportFile'); const exportedString = exportPlugin?.exportAsString('csv', { bom: false, columnDelimiter: ',', columnHeaders: false, exportHiddenColumns: true, exportHiddenRows: true, rowDelimiter: '\r\n', rowHeaders: true, });
console.log(exportedString); };
return ( <> <div className="controls"> <button id="export-string" onClick={() => buttonClickCallback()}> Export as a string </button> </div> <HotTable ref={hotRef} data={[ ['A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1'], ['A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2'], ['A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3'], ['A4', 'B4', 'C4', 'D4', 'E4', 'F4', 'G4'], ['A5', 'B5', 'C5', 'D5', 'E5', 'F5', 'G5'], ['A6', 'B6', 'C6', 'D6', 'E6', 'F6', 'G6'], ['A7', 'B7', 'C7', 'D7', 'E7', 'F7', 'G7'], ]} colHeaders={true} rowHeaders={true} hiddenRows={{ rows: [1, 3, 5], indicators: true }} hiddenColumns={{ columns: [1, 3, 5], indicators: true }} height="auto" autoWrapRow={true} autoWrapCol={true} licenseKey="non-commercial-and-evaluation" /> </> );};
export default ExampleComponent;import { useRef } from 'react';import { HotTable, HotTableRef } from '@handsontable/react-wrapper';import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modulesregisterAllModules();
const ExampleComponent = () => { const hotRef = useRef<HotTableRef>(null);
const buttonClickCallback = () => { const hot = hotRef.current?.hotInstance; const exportPlugin = hot?.getPlugin('exportFile'); const exportedString = exportPlugin?.exportAsString('csv', { bom: false, columnDelimiter: ',', columnHeaders: false, exportHiddenColumns: true, exportHiddenRows: true, rowDelimiter: '\r\n', rowHeaders: true, });
console.log(exportedString); };
return ( <> <div className="controls"> <button id="export-string" onClick={() => buttonClickCallback()}> Export as a string </button> </div> <HotTable ref={hotRef} data={[ ['A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1'], ['A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2'], ['A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3'], ['A4', 'B4', 'C4', 'D4', 'E4', 'F4', 'G4'], ['A5', 'B5', 'C5', 'D5', 'E5', 'F5', 'G5'], ['A6', 'B6', 'C6', 'D6', 'E6', 'F6', 'G6'], ['A7', 'B7', 'C7', 'D7', 'E7', 'F7', 'G7'], ]} colHeaders={true} rowHeaders={true} hiddenRows={{ rows: [1, 3, 5], indicators: true }} hiddenColumns={{ columns: [1, 3, 5], indicators: true }} height="auto" autoWrapRow={true} autoWrapCol={true} licenseKey="non-commercial-and-evaluation" /> </> );};
export default ExampleComponent;Prevent CSV Injection attack
“CSV Injection, also known as Formula Injection, occurs when websites embed untrusted input inside CSV files. When a spreadsheet program such as Microsoft Excel or LibreOffice Calc is used to open a CSV, any cells starting with = will be interpreted by the software as a formula.” (from OWASP website)
To prevent this attack, set the sanitizeValues option when exporting your data in CSV format.
import { useRef } from 'react';import { HotTable } from '@handsontable/react-wrapper';import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modulesregisterAllModules();
const ExampleComponent = () => { const hotRef = useRef(null); const downloadWithNoSanitizationCallback = () => { const hot = hotRef.current?.hotInstance; const exportPlugin = hot?.getPlugin('exportFile');
exportPlugin?.downloadFile('csv', { bom: false, columnDelimiter: ',', columnHeaders: false, exportHiddenColumns: true, exportHiddenRows: true, fileExtension: 'csv', filename: 'Handsontable-CSV-file_[YYYY]-[MM]-[DD]', mimeType: 'text/csv', rowDelimiter: '\r\n', }); };
const downloadWithRecommendedSanitizationCallback = () => { const hot = hotRef.current?.hotInstance; const exportPlugin = hot?.getPlugin('exportFile');
exportPlugin?.downloadFile('csv', { bom: false, columnDelimiter: ',', columnHeaders: false, exportHiddenColumns: true, exportHiddenRows: true, fileExtension: 'csv', filename: 'Handsontable-CSV-file_[YYYY]-[MM]-[DD]', mimeType: 'text/csv', rowDelimiter: '\r\n', sanitizeValues: true, }); };
const downloadWithRegexpSanitizationCallback = () => { const hot = hotRef.current?.hotInstance; const exportPlugin = hot?.getPlugin('exportFile');
exportPlugin?.downloadFile('csv', { bom: false, columnDelimiter: ',', columnHeaders: false, exportHiddenColumns: true, exportHiddenRows: true, fileExtension: 'csv', filename: 'Handsontable-CSV-file_[YYYY]-[MM]-[DD]', mimeType: 'text/csv', rowDelimiter: '\r\n', sanitizeValues: /WEBSERVICE/, }); };
const downloadWithFunctionSanitizationCallback = () => { const hot = hotRef.current?.hotInstance; const exportPlugin = hot?.getPlugin('exportFile');
exportPlugin?.downloadFile('csv', { bom: false, columnDelimiter: ',', columnHeaders: false, exportHiddenColumns: true, exportHiddenRows: true, fileExtension: 'csv', filename: 'Handsontable-CSV-file_[YYYY]-[MM]-[DD]', mimeType: 'text/csv', rowDelimiter: '\r\n', sanitizeValues: (value) => { return /WEBSERVICE/.test(value) ? 'REMOVED SUSPICIOUS CELL CONTENT' : value; }, }); };
return ( <> <div className="example-controls-container"> <div className="controls"> <button onClick={() => downloadWithNoSanitizationCallback()}>Download CSV with no sanitization</button> <button onClick={() => downloadWithRecommendedSanitizationCallback()}> Download CSV with recommended sanitization </button> <button onClick={() => downloadWithRegexpSanitizationCallback()}> Download CSV with sanitization using a regexp </button> <button onClick={() => downloadWithFunctionSanitizationCallback()}> Download CSV with sanitization using a function </button> </div> </div> <HotTable ref={hotRef} data={[ ['https://handsontable.com', '=WEBSERVICE(A1)'], ['https://github.com', '=WEBSERVICE(A2)'], ['http://example.com/malicious-script.exe', '=WEBSERVICE(A3)'], ]} colHeaders={true} rowHeaders={true} height="auto" autoWrapRow={true} autoWrapCol={true} licenseKey="non-commercial-and-evaluation" /> </> );};
export default ExampleComponent;import { useRef } from 'react';import { HotTable, HotTableRef } from '@handsontable/react-wrapper';import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modulesregisterAllModules();
const ExampleComponent = () => { const hotRef = useRef<HotTableRef>(null);
const downloadWithNoSanitizationCallback = () => { const hot = hotRef.current?.hotInstance; const exportPlugin = hot?.getPlugin('exportFile');
exportPlugin?.downloadFile('csv', { bom: false, columnDelimiter: ',', columnHeaders: false, exportHiddenColumns: true, exportHiddenRows: true, fileExtension: 'csv', filename: 'Handsontable-CSV-file_[YYYY]-[MM]-[DD]', mimeType: 'text/csv', rowDelimiter: '\r\n', }); };
const downloadWithRecommendedSanitizationCallback = () => { const hot = hotRef.current?.hotInstance; const exportPlugin = hot?.getPlugin('exportFile');
exportPlugin?.downloadFile('csv', { bom: false, columnDelimiter: ',', columnHeaders: false, exportHiddenColumns: true, exportHiddenRows: true, fileExtension: 'csv', filename: 'Handsontable-CSV-file_[YYYY]-[MM]-[DD]', mimeType: 'text/csv', rowDelimiter: '\r\n', sanitizeValues: true, }); };
const downloadWithRegexpSanitizationCallback = () => { const hot = hotRef.current?.hotInstance; const exportPlugin = hot?.getPlugin('exportFile');
exportPlugin?.downloadFile('csv', { bom: false, columnDelimiter: ',', columnHeaders: false, exportHiddenColumns: true, exportHiddenRows: true, fileExtension: 'csv', filename: 'Handsontable-CSV-file_[YYYY]-[MM]-[DD]', mimeType: 'text/csv', rowDelimiter: '\r\n', sanitizeValues: /WEBSERVICE/, }); };
const downloadWithFunctionSanitizationCallback = () => { const hot = hotRef.current?.hotInstance; const exportPlugin = hot?.getPlugin('exportFile');
exportPlugin?.downloadFile('csv', { bom: false, columnDelimiter: ',', columnHeaders: false, exportHiddenColumns: true, exportHiddenRows: true, fileExtension: 'csv', filename: 'Handsontable-CSV-file_[YYYY]-[MM]-[DD]', mimeType: 'text/csv', rowDelimiter: '\r\n', sanitizeValues: (value) => { return /WEBSERVICE/.test(value) ? 'REMOVED SUSPICIOUS CELL CONTENT' : value; }, }); };
return ( <> <div className="example-controls-container"> <div className="controls"> <button onClick={() => downloadWithNoSanitizationCallback()}>Download CSV with no sanitization</button> <button onClick={() => downloadWithRecommendedSanitizationCallback()}> Download CSV with recommended sanitization </button> <button onClick={() => downloadWithRegexpSanitizationCallback()}> Download CSV with sanitization using a regexp </button> <button onClick={() => downloadWithFunctionSanitizationCallback()}> Download CSV with sanitization using a function </button> </div> </div> <HotTable ref={hotRef} data={[ ['https://handsontable.com', '=WEBSERVICE(A1)'], ['https://github.com', '=WEBSERVICE(A2)'], ['http://example.com/malicious-script.exe', '=WEBSERVICE(A3)'], ]} colHeaders={true} rowHeaders={true} height="auto" autoWrapRow={true} autoWrapCol={true} licenseKey="non-commercial-and-evaluation" /> </> );};
export default ExampleComponent;Available methods
The plugin exposes the following methods to export data.
downloadFile(format, options)- generates a downloadable file directly in the browser. Synchronous; supports text-based formats only (e.g. CSV). For XLSX, usedownloadFileAsync.downloadFileAsync(format, options)- generates a downloadable file and returns aPromise. Supports all formats including XLSX.exportAsBlob(format, options)- allows you to export a JavaScript Blob object.exportAsString(format, options)- allows you to export data as a string. Supports text-based formats only (e.g. CSV).
Each method takes two parameters. The first, format, is required. The second, options, is an optional object that overrides or extends the default export configuration. The table below lists all supported options for CSV export.
Available options in the export configuration
| Property | Type / Default | Description |
|---|---|---|
bom | Boolean, default true | Prepend output with BOM (UTF-8). Browser uses EF BB BF. |
columnDelimiter | String, default ',' | Column delimiter. |
columnHeaders | Boolean, default false | Include column headers. Does not support the NestedHeaders plugin. |
exportHiddenColumns | Boolean, default false | Include hidden columns. |
exportHiddenRows | Boolean, default false | Include hidden rows. |
fileExtension | String, default 'csv' | File extension. Used by downloadFile(). |
filename | String, default 'Handsontable [YYYY]-[MM]-[DD]' | File name. Placeholders [YYYY], [MM], [DD] are replaced with the current date. Used by downloadFile(). |
mimeType | String, default 'text/csv' | MIME type. Used by downloadFile() and exportAsBlob(). |
range | Array, default [] | Cell range to export: [startRow, startColumn, endRow, endColumn] (visual indexes). |
rowDelimiter | String, default '\r\n' | Row delimiter. |
rowHeaders | Boolean, default false | Include row headers. |
sanitizeValues | Boolean | RegExp | Function, default false | Value sanitization. true = OWASP CSV injection rules; RegExp = escape matching values; Function = replace with return value. |
Related API reference
Plugins