Posted 17 January 2024, 7:56 pm EST
Hi,
I successfully reproduced the observed behavior, and by using “GC.Spread.Sheets.CalculationType.rebuild,” all the formulas within the specified range are rebuilt and marked as dirty for recalculation. This, in turn, triggers the rangeChanged event, even for default values like “Loading…” . There is no direct way to prevent the event from triggering for the default value of an asynchronous formula.
But you could use below steps to achieve your requirements:
- Before recalculating formulas, store information about the cell values where the formula is used by using the getUsedRange and getArray methods. Refer to the snippet below.
getFomulaInfo( spread: GC.Spread.Sheets.Workbook){
let data = {};
spread.sheets.forEach( sheet => {
const usedRangeFormula = sheet.getUsedRange(GC.Spread.Sheets.UsedRangeType.formula);
const formulaLocation = sheet.getArray(usedRangeFormula.row, usedRangeFormula.col, usedRangeFormula.rowCount, usedRangeFormula.colCount, true);
// creating datamap for formula cells only
for( let i = usedRangeFormula.row; i < usedRangeFormula.row + usedRangeFormula.rowCount; i++){
for( let j = usedRangeFormula.col; j < usedRangeFormula.col + usedRangeFormula.colCount; j++){
if(formulaLocation[i - usedRangeFormula.row][j - usedRangeFormula.col]){
if(!data[sheet.name()]){
data[sheet.name()] = {};
data[sheet.name()][i] = {};
}else if(!data[sheet.name()][i]){
data[sheet.name()][i] = {}
}
data[sheet.name()][i][j] = sheet.getValue( i, j);
}
}
}
})
return data;
}
-
Then do recalculation.
-
After that, simply check in the rangeChanged event whether the changed value is neither the default value nor the old value. If this condition is met, apply a background color to indicate the changed value. Refer to the snippet below.
spread.bind(GC.Spread.Sheets.Events.RangeChanged, (e: any, info: any) => {
// check if formula info is not null and formual present in sheet
if( formulaInfo && formulaInfo[info.sheetName]){
info.changedCells.forEach( (cell: any) => {
// ignore defualt and old value
if( info.sheet.getValue(cell.row, cell.col) !== "Loading..." && formulaInfo[info.sheetName][cell.row][cell.col] !== info.sheet.getValue(cell.row, cell.col)){
info.sheet.getCell( cell.row, cell.col).backColor("yellow")
}
})
}
})
I have attached a sample to refer.
Sample: https://jscodemine.grapecity.com/share/Sqh1F5a6VU2TABI_ZDpXzA/?IsEmbed=false&Theme=Unset&PreviewDirection=0&IsEditorShow=true&IsExplorerShow=true&IsPreviewShow=true&IsConsoleShow=true&IsRunBTNShow=false&IsResetBTNShow=false&IsOpenInCodemineBTNShow=false&PanelWidth=20&PanelWidth=50&PanelWidth=30&defaultOpen={"OpenedFileName"%3A["%2Findex.html"%2C"%2Fsrc%2Fapp.component.ts"%2C"%2Fsrc%2Fapp.component.html"]%2C"ActiveFile"%3A"%2Fsrc%2Fapp.component.ts"}
References:
getUsedRange: https://developer.mescius.com/spreadjs/api/classes/GC.Spread.Sheets.Worksheet#getusedrange
getArray: https://developer.mescius.com/spreadjs/api/classes/GC.Spread.Sheets.Worksheet#getarray
Best regards,
Ankit