mirror of
https://github.com/ruilisi/fortune-sheet.git
synced 2025-01-07 03:16:50 +08:00
fixed: formula optimization bugfixes, renaming variables, defining types
This commit is contained in:
parent
d36e50e72b
commit
12c2c0c2f1
@ -19,7 +19,7 @@ import { jfrefreshgrid } from "../modules/refresh";
|
||||
import { setRowHeight } from "../api";
|
||||
import { CFSplitRange } from "../modules";
|
||||
import clipboard from "../modules/clipboard";
|
||||
import { setFormulaObject } from "../modules/formulaHelper";
|
||||
import { setFormulaCellInfo } from "../modules/formulaHelper";
|
||||
|
||||
function postPasteCut(
|
||||
ctx: Context,
|
||||
@ -33,7 +33,7 @@ function postPasteCut(
|
||||
// clearTimeout(refreshCanvasTimeOut);
|
||||
for (let r = source.range.row[0]; r <= source.range.row[1]; r += 1) {
|
||||
for (let c = source.range.column[0]; c <= source.range.column[1]; c += 1) {
|
||||
setFormulaObject(ctx, { r, c, id: source.sheetId });
|
||||
setFormulaCellInfo(ctx, { r, c, id: source.sheetId });
|
||||
if (`${r}_${c}_${source.sheetId}` in execF_rc) {
|
||||
continue;
|
||||
}
|
||||
@ -45,7 +45,7 @@ function postPasteCut(
|
||||
|
||||
for (let r = target.range.row[0]; r <= target.range.row[1]; r += 1) {
|
||||
for (let c = target.range.column[0]; c <= target.range.column[1]; c += 1) {
|
||||
setFormulaObject(ctx, { r, c, id: source.sheetId });
|
||||
setFormulaCellInfo(ctx, { r, c, id: source.sheetId });
|
||||
if (`${r}_${c}_${target.sheetId}` in execF_rc) {
|
||||
continue;
|
||||
}
|
||||
|
@ -63,17 +63,17 @@ export function setConditionRules(
|
||||
const rangeArr = getRangeByTxt(ctx, v);
|
||||
// 判断条件值是不是选区
|
||||
if (rangeArr.length > 1) {
|
||||
const r1 = rangeArr[0].row[0];
|
||||
const r2 = rangeArr[0].row[1];
|
||||
const c1 = rangeArr[0].column[0];
|
||||
const c2 = rangeArr[0].column[1];
|
||||
const r1 = rangeArr?.[0]?.row[0];
|
||||
const r2 = rangeArr?.[0]?.row[1];
|
||||
const c1 = rangeArr?.[0]?.column[0];
|
||||
const c2 = rangeArr?.[0]?.column[1];
|
||||
if (r1 === r2 && c1 === c2) {
|
||||
const d = getFlowdata(ctx);
|
||||
if (!d) return;
|
||||
if (!d || _.isNil(r1) || _.isNil(c1)) return;
|
||||
v = getCellValue(r1, c1, d);
|
||||
conditionRange.push({
|
||||
row: rangeArr[0].row,
|
||||
column: rangeArr[0].column,
|
||||
row: rangeArr?.[0]?.row,
|
||||
column: rangeArr?.[0]?.column,
|
||||
});
|
||||
conditionValue.push(v);
|
||||
} else {
|
||||
@ -97,17 +97,17 @@ export function setConditionRules(
|
||||
return;
|
||||
}
|
||||
if (rangeArr1.length === 1) {
|
||||
const r1 = rangeArr1[0].row[0];
|
||||
const r2 = rangeArr1[0].row[1];
|
||||
const c1 = rangeArr1[0].column[0];
|
||||
const c2 = rangeArr1[0].column[1];
|
||||
const r1 = rangeArr1?.[0]?.row[0];
|
||||
const r2 = rangeArr1?.[0]?.row[1];
|
||||
const c1 = rangeArr1?.[0]?.column[0];
|
||||
const c2 = rangeArr1?.[0]?.column[1];
|
||||
if (r1 === r2 && c1 === c2) {
|
||||
const d = getFlowdata(ctx);
|
||||
if (!d) return;
|
||||
if (!d || _.isNil(r1) || _.isNil(c1)) return;
|
||||
v1 = getCellValue(r1, c1, d);
|
||||
conditionRange.push({
|
||||
row: rangeArr1[0].row,
|
||||
column: rangeArr1[0].column,
|
||||
row: rangeArr1?.[0]?.row,
|
||||
column: rangeArr1?.[0]?.column,
|
||||
});
|
||||
conditionValue.push(v1);
|
||||
} else {
|
||||
@ -127,17 +127,17 @@ export function setConditionRules(
|
||||
return;
|
||||
}
|
||||
if (rangeArr2.length === 1) {
|
||||
const r1 = rangeArr2[0].row[0];
|
||||
const r2 = rangeArr2[0].row[1];
|
||||
const c1 = rangeArr2[0].column[0];
|
||||
const c2 = rangeArr2[0].column[1];
|
||||
const r1 = rangeArr2?.[0]?.row[0];
|
||||
const r2 = rangeArr2?.[0]?.row[1];
|
||||
const c1 = rangeArr2?.[0]?.column[0];
|
||||
const c2 = rangeArr2?.[0]?.column[1];
|
||||
if (r1 === r2 && c1 === c2) {
|
||||
const d = getFlowdata(ctx);
|
||||
if (!d) return;
|
||||
if (!d || _.isNil(r1) || _.isNil(c1)) return;
|
||||
v2 = getCellValue(r1, c1, d);
|
||||
conditionRange.push({
|
||||
row: rangeArr2[0].row,
|
||||
column: rangeArr2[0].column,
|
||||
row: rangeArr2?.[0]?.row,
|
||||
column: rangeArr2?.[0]?.column,
|
||||
});
|
||||
} else {
|
||||
ctx.warnDialog = conditionformat.onlySingleCell;
|
||||
|
@ -1,6 +1,13 @@
|
||||
import _ from "lodash";
|
||||
import { Context, getFlowdata } from "../context";
|
||||
import { Cell, CellMatrix, Range, Selection, SingleRange } from "../types";
|
||||
import {
|
||||
Cell,
|
||||
CellMatrix,
|
||||
FormulaDependency,
|
||||
Range,
|
||||
Selection,
|
||||
SingleRange,
|
||||
} from "../types";
|
||||
import { getSheetIndex, indexToColumnChar, rgbToHex } from "../utils";
|
||||
import { checkCF, getComputeMap } from "./ConditionFormat";
|
||||
import { getFailureText, validateCellData } from "./dataVerification";
|
||||
@ -21,7 +28,7 @@ import {
|
||||
} from "./inline-string";
|
||||
import { isRealNull, isRealNum, valueIsError } from "./validation";
|
||||
import { getCellTextInfo } from "./text";
|
||||
import { setFormulaObject } from "./formulaHelper";
|
||||
import { setFormulaCellInfo } from "./formulaHelper";
|
||||
|
||||
// TODO put these in context ref
|
||||
// let rangestart = false;
|
||||
@ -1082,7 +1089,7 @@ export function updateCell(
|
||||
});
|
||||
}
|
||||
|
||||
setFormulaObject(ctx, { r, c, id: ctx.currentSheetId });
|
||||
setFormulaCellInfo(ctx, { r, c, id: ctx.currentSheetId });
|
||||
ctx.formulaCache.execFunctionGlobalData = null;
|
||||
}
|
||||
|
||||
@ -1210,7 +1217,7 @@ export function getRangetxt(
|
||||
|
||||
// 把string A1:A2转为选区数组
|
||||
export function getRangeByTxt(ctx: Context, txt: string) {
|
||||
let range = [];
|
||||
let range: (FormulaDependency | null)[] = [];
|
||||
if (txt.indexOf(",") !== -1) {
|
||||
const arr = txt.split(",");
|
||||
for (let i = 0; i < arr.length; i += 1) {
|
||||
|
@ -1,3 +1,4 @@
|
||||
import _ from "lodash";
|
||||
import {
|
||||
colLocationByIndex,
|
||||
Context,
|
||||
@ -39,9 +40,9 @@ export function dataRangeSelection(
|
||||
ctx.luckysheetCellUpdate = [row_index, col_index];
|
||||
|
||||
const range = getRangeByTxt(ctx, rangT);
|
||||
const r = range[0].row;
|
||||
const c = range[0].column;
|
||||
|
||||
const r = range?.[0]?.row;
|
||||
const c = range?.[0]?.column;
|
||||
if (_.isNil(r) || _.isNil(c)) return;
|
||||
const row_pre = rowLocationByIndex(r[0], ctx.visibledatarow)[0];
|
||||
const row = rowLocationByIndex(r[1], ctx.visibledatarow)[1];
|
||||
const col_pre = colLocationByIndex(c[0], ctx.visibledatacolumn)[0];
|
||||
@ -69,9 +70,12 @@ export function getDropdownList(ctx: Context, txt: string) {
|
||||
const list: (string | number | boolean)[] = [];
|
||||
if (iscelldata(txt)) {
|
||||
const range = getcellrange(ctx, txt);
|
||||
const index = getSheetIndex(ctx, range.sheetId) as number;
|
||||
const index = getSheetIndex(
|
||||
ctx,
|
||||
range?.sheetId || ctx.currentSheetId
|
||||
) as number;
|
||||
const d = ctx.luckysheetfile[index].data;
|
||||
if (!d) return [];
|
||||
if (!d || !range) return [];
|
||||
for (let r = range.row[0]; r <= range.row[1]; r += 1) {
|
||||
for (let c = range.column[0]; c <= range.column[1]; c += 1) {
|
||||
if (!d[r]) {
|
||||
@ -854,12 +858,13 @@ export function confirmMessage(
|
||||
ctx.warnDialog = generalDialog.noSeletionError;
|
||||
return false;
|
||||
}
|
||||
let str = range[range.length - 1].row[0];
|
||||
let edr = range[range.length - 1].row[1];
|
||||
let stc = range[range.length - 1].column[0];
|
||||
let edc = range[range.length - 1].column[1];
|
||||
let str = range?.[range.length - 1]?.row[0];
|
||||
let edr = range?.[range.length - 1]?.row[1];
|
||||
let stc = range?.[range.length - 1]?.column[0];
|
||||
let edc = range?.[range.length - 1]?.column[1];
|
||||
const d = getFlowdata(ctx);
|
||||
if (!d) return false;
|
||||
if (!d || _.isNil(str) || _.isNil(edr) || _.isNil(stc) || _.isNil(edc))
|
||||
return false;
|
||||
if (str < 0) {
|
||||
str = 0;
|
||||
}
|
||||
|
@ -1,7 +1,17 @@
|
||||
import _ from "lodash";
|
||||
// @ts-ignore
|
||||
import { Parser, ERROR_REF } from "@fortune-sheet/formula-parser";
|
||||
import type { Cell, CellMatrix, History, Rect, Selection } from "../types";
|
||||
import type {
|
||||
Cell,
|
||||
CellMatrix,
|
||||
FormulaDependency,
|
||||
FormulaDependenciesMap,
|
||||
FormulaCell,
|
||||
FormulaCellInfoMap,
|
||||
History,
|
||||
Rect,
|
||||
Selection,
|
||||
} from "../types";
|
||||
import { Context, getFlowdata } from "../context";
|
||||
import {
|
||||
columnCharToIndex,
|
||||
@ -21,7 +31,7 @@ import { cancelFunctionrangeSelected, seletedHighlistByindex } from ".";
|
||||
import {
|
||||
arrayMatch,
|
||||
executeAffectedFormulas,
|
||||
setFormulaObject,
|
||||
setFormulaCellInfo,
|
||||
getFormulaRunList,
|
||||
} from "./formulaHelper";
|
||||
|
||||
@ -98,9 +108,9 @@ export class FormulaCache {
|
||||
execFunctionGlobalData: any;
|
||||
|
||||
// useful in cut-paste operation where several cells may be affected but the formulas remains the same
|
||||
formulaArrayCache: any;
|
||||
formulaDependenciesMap: FormulaDependenciesMap;
|
||||
|
||||
formulaObjects: any;
|
||||
formulaCellInfoMap: FormulaCellInfoMap | null;
|
||||
|
||||
constructor() {
|
||||
const that = this;
|
||||
@ -108,8 +118,8 @@ export class FormulaCache {
|
||||
this.selectingRangeIndex = -1;
|
||||
this.functionlistMap = {};
|
||||
this.execFunctionGlobalData = {};
|
||||
this.formulaArrayCache = {};
|
||||
this.formulaObjects = null;
|
||||
this.formulaDependenciesMap = {};
|
||||
this.formulaCellInfoMap = null;
|
||||
this.cellTextToIndexList = {};
|
||||
this.parser = new Parser();
|
||||
this.parser.on(
|
||||
@ -191,7 +201,7 @@ export class FormulaCache {
|
||||
function requestUpdate(value: any) {
|
||||
if (value instanceof Object) {
|
||||
if (value.r !== undefined && value.r !== undefined) {
|
||||
setFormulaObject(
|
||||
setFormulaCellInfo(
|
||||
ctx,
|
||||
{ r: value.r, c: value.c, id: ctx.currentSheetId },
|
||||
data
|
||||
@ -302,7 +312,7 @@ export function getcellrange(
|
||||
txt: string,
|
||||
formulaId?: string,
|
||||
data?: CellMatrix
|
||||
) {
|
||||
): FormulaDependency | null {
|
||||
if (_.isNil(txt) || txt.length === 0) {
|
||||
return null;
|
||||
}
|
||||
@ -310,7 +320,7 @@ export function getcellrange(
|
||||
|
||||
let sheettxt = "";
|
||||
let rangetxt = "";
|
||||
let sheetId = null;
|
||||
let sheetId;
|
||||
let sheetdata = null;
|
||||
|
||||
const { luckysheetfile } = ctx;
|
||||
@ -369,7 +379,7 @@ export function getcellrange(
|
||||
const col = columnCharToIndex(rangetxt.replace(/[^A-Za-z]/g, ""));
|
||||
|
||||
if (!Number.isNaN(row) && !Number.isNaN(col)) {
|
||||
const item = {
|
||||
const item: FormulaDependency = {
|
||||
row: [row, row],
|
||||
column: [col, col],
|
||||
sheetId,
|
||||
@ -380,8 +390,8 @@ export function getcellrange(
|
||||
return null;
|
||||
}
|
||||
const rangetxtArr = rangetxt.split(":");
|
||||
const row = [];
|
||||
const col = [];
|
||||
const row: [number, number] = [-1, -1];
|
||||
const col: [number, number] = [-1, -1];
|
||||
row[0] = parseInt(rangetxtArr[0].replace(/[^0-9]/g, ""), 10) - 1;
|
||||
row[1] = parseInt(rangetxtArr[1].replace(/[^0-9]/g, ""), 10) - 1;
|
||||
if (Number.isNaN(row[0])) {
|
||||
@ -405,7 +415,7 @@ export function getcellrange(
|
||||
return null;
|
||||
}
|
||||
|
||||
const item = {
|
||||
const item: FormulaDependency = {
|
||||
row,
|
||||
column: col,
|
||||
sheetId,
|
||||
@ -832,25 +842,11 @@ export function isFunctionRange(
|
||||
|
||||
export function getAllFunctionGroup(ctx: Context) {
|
||||
const { luckysheetfile } = ctx;
|
||||
let ret: any[] = [];
|
||||
let ret: FormulaCell[] = [];
|
||||
for (let i = 0; i < luckysheetfile.length; i += 1) {
|
||||
const file = luckysheetfile[i];
|
||||
let { calcChain } = file;
|
||||
|
||||
/* 备注:再次加载表格获取的数据可能是JSON字符串格式(需要进行发序列化处理) */
|
||||
// if (calcChain) {
|
||||
// const tempCalcChain: any[] = [];
|
||||
// calcChain.forEach((item) => {
|
||||
// if (typeof item === "string") {
|
||||
// tempCalcChain.push(JSON.parse(item));
|
||||
// } else {
|
||||
// tempCalcChain.push(item);
|
||||
// }
|
||||
// });
|
||||
// calcChain = tempCalcChain;
|
||||
// file.calcChain = tempCalcChain;
|
||||
// }
|
||||
|
||||
let { dynamicArray_compute } = file;
|
||||
if (_.isNil(calcChain)) {
|
||||
calcChain = [];
|
||||
@ -1187,14 +1183,14 @@ export function groupValuesRefresh(ctx: Context) {
|
||||
}
|
||||
}
|
||||
|
||||
function setFormulaObjectsCache(
|
||||
export function setFormulaCellInfoMap(
|
||||
ctx: Context,
|
||||
calcChains: any,
|
||||
data: CellMatrix
|
||||
data?: CellMatrix
|
||||
) {
|
||||
for (let i = 0; i < calcChains.length; i += 1) {
|
||||
const formulaCell = calcChains[i];
|
||||
setFormulaObject(ctx, formulaCell, data);
|
||||
setFormulaCellInfo(ctx, formulaCell, data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1232,7 +1228,7 @@ export function execFunctionGroup(
|
||||
}
|
||||
|
||||
// 1. get list of all functions in the sheet
|
||||
const calcChains = getAllFunctionGroup(ctx); // { "r": r, "c": c, "id": id, "func": func}
|
||||
const calcChains: FormulaCell[] = getAllFunctionGroup(ctx);
|
||||
|
||||
// 2. Store the cells involved in the modification
|
||||
const updateValueObjects: any = {};
|
||||
@ -1247,30 +1243,33 @@ export function execFunctionGroup(
|
||||
}
|
||||
}
|
||||
|
||||
// 3. formulaObjects: a cache of ALL formulas vs their ranges
|
||||
if (!ctx.formulaCache.formulaObjects) {
|
||||
ctx.formulaCache.formulaObjects = {};
|
||||
setFormulaObjectsCache(ctx, calcChains, data);
|
||||
// 3. formulaCellInfoMap: a cache of ALL formulas vs their ranges
|
||||
if (
|
||||
!ctx.formulaCache.formulaCellInfoMap ||
|
||||
_.isEmpty(ctx.formulaCache.formulaCellInfoMap)
|
||||
) {
|
||||
ctx.formulaCache.formulaCellInfoMap = {};
|
||||
setFormulaCellInfoMap(ctx, calcChains, data);
|
||||
}
|
||||
const { formulaObjects } = ctx.formulaCache;
|
||||
const { formulaCellInfoMap } = ctx.formulaCache;
|
||||
|
||||
// 4. Form a graph structure of references between formulas
|
||||
// basically fills parents in formulaObjects[i]
|
||||
// basically fills parents in formulaCellInfoMap[i]
|
||||
const updateValueArray: any = [];
|
||||
const arrayMatchCache: Record<
|
||||
string,
|
||||
{ key: string; r: number; c: number; sheetId: string }[]
|
||||
> = {};
|
||||
Object.keys(formulaObjects).forEach((key) => {
|
||||
const formulaObject = formulaObjects[key];
|
||||
Object.keys(formulaCellInfoMap).forEach((key) => {
|
||||
const formulaObject = formulaCellInfoMap[key];
|
||||
arrayMatch(
|
||||
arrayMatchCache,
|
||||
formulaObject.formulaArray,
|
||||
formulaObjects,
|
||||
formulaObject.formulaDependency,
|
||||
formulaCellInfoMap,
|
||||
updateValueObjects,
|
||||
(childKey: string) => {
|
||||
if (childKey in formulaObjects) {
|
||||
const childFormulaObject = formulaObjects[childKey];
|
||||
if (childKey in formulaCellInfoMap) {
|
||||
const childFormulaObject = formulaCellInfoMap[childKey];
|
||||
// formulaObject.chidren[childKey] = 1; not needed
|
||||
childFormulaObject.parents[key] = 1;
|
||||
}
|
||||
@ -1286,7 +1285,10 @@ export function execFunctionGroup(
|
||||
});
|
||||
|
||||
// 5. Get list of affected formulas using the graph structure by depth-first traversal
|
||||
const formulaRunList = getFormulaRunList(updateValueArray, formulaObjects);
|
||||
const formulaRunList = getFormulaRunList(
|
||||
updateValueArray,
|
||||
formulaCellInfoMap
|
||||
);
|
||||
|
||||
// 6. execute relevant formulas
|
||||
executeAffectedFormulas(ctx, formulaRunList, calcChains);
|
||||
@ -1540,7 +1542,7 @@ export function createRangeHightlight(
|
||||
return;
|
||||
if (
|
||||
cellrange.sheetId === ctx.currentSheetId ||
|
||||
(cellrange.sheetId === -1 &&
|
||||
(!cellrange.sheetId &&
|
||||
ctx.formulaCache.rangetosheet === ctx.currentSheetId)
|
||||
) {
|
||||
const rect = seletedHighlistByindex(
|
||||
|
@ -3,6 +3,8 @@ import {
|
||||
CellMatrix,
|
||||
Context,
|
||||
execfunction,
|
||||
FormulaCell,
|
||||
FormulaCellInfo,
|
||||
getcellFormula,
|
||||
getcellrange,
|
||||
iscelldata,
|
||||
@ -10,9 +12,9 @@ import {
|
||||
} from "..";
|
||||
|
||||
// Make sure setFormulaObject() is executed *after* the cell modifications
|
||||
export function setFormulaObject(
|
||||
export function setFormulaCellInfo(
|
||||
ctx: Context,
|
||||
formulaCell: any,
|
||||
formulaCell: FormulaCell,
|
||||
data?: CellMatrix
|
||||
) {
|
||||
const key = `r${formulaCell.r}c${formulaCell.c}i${formulaCell.id}`;
|
||||
@ -24,7 +26,7 @@ export function setFormulaObject(
|
||||
data
|
||||
);
|
||||
if (_.isNil(calc_funcStr)) {
|
||||
delete ctx.formulaCache.formulaObjects?.[key];
|
||||
delete ctx.formulaCache.formulaCellInfoMap?.[key];
|
||||
return;
|
||||
}
|
||||
const txt1 = calc_funcStr.toUpperCase();
|
||||
@ -33,8 +35,9 @@ export function setFormulaObject(
|
||||
txt1.indexOf("OFFSET(") > -1 ||
|
||||
txt1.indexOf("INDEX(") > -1;
|
||||
|
||||
const formulaArray = ctx.formulaCache.formulaArrayCache[calc_funcStr] || [];
|
||||
if (formulaArray.length === 0) {
|
||||
const formulaDependency =
|
||||
ctx.formulaCache.formulaDependenciesMap[calc_funcStr] || [];
|
||||
if (formulaDependency.length === 0) {
|
||||
if (isOffsetFunc) {
|
||||
isFunctionRange(
|
||||
ctx,
|
||||
@ -46,7 +49,7 @@ export function setFormulaObject(
|
||||
(str_nb: string) => {
|
||||
const range = getcellrange(ctx, _.trim(str_nb), formulaCell.id, data);
|
||||
if (!_.isNil(range)) {
|
||||
formulaArray.push(range);
|
||||
formulaDependency.push(range);
|
||||
}
|
||||
}
|
||||
);
|
||||
@ -170,15 +173,15 @@ export function setFormulaObject(
|
||||
continue;
|
||||
}
|
||||
|
||||
formulaArray.push(range);
|
||||
formulaDependency.push(range);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ctx.formulaCache.formulaArrayCache[calc_funcStr])
|
||||
ctx.formulaCache.formulaArrayCache[calc_funcStr] = formulaArray;
|
||||
if (!ctx.formulaCache.formulaDependenciesMap[calc_funcStr])
|
||||
ctx.formulaCache.formulaDependenciesMap[calc_funcStr] = formulaDependency;
|
||||
|
||||
const item = {
|
||||
formulaArray,
|
||||
const item: FormulaCellInfo = {
|
||||
formulaDependency,
|
||||
calc_funcStr,
|
||||
key,
|
||||
r: formulaCell.r,
|
||||
@ -189,8 +192,9 @@ export function setFormulaObject(
|
||||
color: "w",
|
||||
};
|
||||
|
||||
if (!ctx.formulaCache.formulaObjects) ctx.formulaCache.formulaObjects = {};
|
||||
ctx.formulaCache.formulaObjects[key] = item;
|
||||
if (!ctx.formulaCache.formulaCellInfoMap)
|
||||
ctx.formulaCache.formulaCellInfoMap = {};
|
||||
ctx.formulaCache.formulaCellInfoMap[key] = item;
|
||||
}
|
||||
|
||||
export function executeAffectedFormulas(
|
||||
@ -240,7 +244,7 @@ export function executeAffectedFormulas(
|
||||
|
||||
export function getFormulaRunList(
|
||||
updateValueArray: any[],
|
||||
formulaObjects: any
|
||||
formulaCellInfoMap: any
|
||||
) {
|
||||
const formulaRunList = [];
|
||||
let stack = _.cloneDeep(updateValueArray);
|
||||
@ -260,7 +264,7 @@ export function getFormulaRunList(
|
||||
|
||||
const cacheStack: any = [];
|
||||
Object.keys(formulaObject.parents).forEach((parentKey) => {
|
||||
const parentFormulaObject = formulaObjects[parentKey];
|
||||
const parentFormulaObject = formulaCellInfoMap[parentKey];
|
||||
if (!_.isNil(parentFormulaObject)) {
|
||||
cacheStack.push(parentFormulaObject);
|
||||
}
|
||||
@ -282,13 +286,13 @@ export function getFormulaRunList(
|
||||
|
||||
export const arrayMatch = (
|
||||
arrayMatchCache: any,
|
||||
formulaArray: any,
|
||||
_formulaObjects: any,
|
||||
formulaDependency: any,
|
||||
_formulaCellInfoMap: any,
|
||||
_updateValueObjects: any,
|
||||
func: any
|
||||
) => {
|
||||
for (let a = 0; a < formulaArray.length; a += 1) {
|
||||
const range = formulaArray[a];
|
||||
for (let a = 0; a < formulaDependency.length; a += 1) {
|
||||
const range = formulaDependency[a];
|
||||
const cacheKey = `r${range.row[0]}${range.row[1]}c${range.column[0]}${range.column[1]}id${range.sheetId}`;
|
||||
if (cacheKey in arrayMatchCache) {
|
||||
const amc: any[] = arrayMatchCache[cacheKey];
|
||||
@ -302,7 +306,7 @@ export const arrayMatch = (
|
||||
const key = `r${r}c${c}i${range.sheetId}`;
|
||||
func(key, r, c, range.sheetId);
|
||||
if (
|
||||
(_formulaObjects && key in _formulaObjects) ||
|
||||
(_formulaCellInfoMap && key in _formulaCellInfoMap) ||
|
||||
(_updateValueObjects && key in _updateValueObjects)
|
||||
) {
|
||||
functionArr.push({
|
||||
@ -315,7 +319,7 @@ export const arrayMatch = (
|
||||
}
|
||||
}
|
||||
|
||||
if (_formulaObjects || _updateValueObjects) {
|
||||
if (_formulaCellInfoMap || _updateValueObjects) {
|
||||
arrayMatchCache[cacheKey] = functionArr;
|
||||
}
|
||||
}
|
||||
|
@ -175,7 +175,7 @@ export function goToLink(
|
||||
scrollbarX.scrollLeft = col_pre;
|
||||
scrollbarY.scrollLeft = row_pre;
|
||||
ctx.luckysheet_select_save = normalizeSelection(ctx, [range]);
|
||||
changeSheet(ctx, range.sheetId);
|
||||
changeSheet(ctx, range.sheetId || ctx.currentSheetId);
|
||||
}
|
||||
ctx.linkCard = undefined;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Context, getFlowdata } from "../context";
|
||||
import { CellMatrix, Selection } from "../types";
|
||||
import { execFunctionGroup } from "./formula";
|
||||
import { setFormulaObject } from "./formulaHelper";
|
||||
import { setFormulaCellInfo } from "./formulaHelper";
|
||||
|
||||
function runExecFunction(
|
||||
ctx: Context,
|
||||
@ -13,7 +13,7 @@ function runExecFunction(
|
||||
for (let s = 0; s < range.length; s += 1) {
|
||||
for (let r = range[s].row[0]; r <= range[s].row[1]; r += 1) {
|
||||
for (let c = range[s].column[0]; c <= range[s].column[1]; c += 1) {
|
||||
setFormulaObject(ctx, { r, c, id: index }, data);
|
||||
setFormulaCellInfo(ctx, { r, c, id: index }, data);
|
||||
ctx.formulaCache.execFunctionExist.push({ r, c, i: index });
|
||||
}
|
||||
}
|
||||
|
@ -1152,6 +1152,7 @@ export function insertRowCol(
|
||||
}
|
||||
|
||||
refreshLocalMergeData(merge_new, file);
|
||||
ctx.formulaCache.formulaCellInfoMap = null;
|
||||
|
||||
// if (type === "row") {
|
||||
// const scrollLeft = $("#luckysheet-cell-main").scrollLeft();
|
||||
@ -2062,6 +2063,7 @@ export function deleteRowCol(
|
||||
file.hyperlink = newHyperlink;
|
||||
|
||||
refreshLocalMergeData(merge_new, file);
|
||||
ctx.formulaCache.formulaCellInfoMap = null;
|
||||
|
||||
if (file.id === ctx.currentSheetId) {
|
||||
ctx.config = cfg;
|
||||
|
@ -6,6 +6,7 @@ import { locale } from "../locale";
|
||||
import { Settings } from "../settings";
|
||||
import { CellMatrix, Sheet } from "../types";
|
||||
import { generateRandomSheetName, getSheetIndex } from "../utils";
|
||||
import { setFormulaCellInfo } from "./formulaHelper";
|
||||
|
||||
function storeSheetParam(ctx: Context) {
|
||||
const index = getSheetIndex(ctx, ctx.currentSheetId);
|
||||
@ -194,7 +195,7 @@ export function updateSheet(ctx: Context, newData: Sheet[]) {
|
||||
const { data, row, column } = newDatum;
|
||||
const index = getSheetIndex(ctx, newDatum.id!) as number;
|
||||
if (data != null) {
|
||||
// 如果row和column存在的话则进行row和column和data进行比较,如果row和column不存在的话则进行data和default进行比较。
|
||||
// If row and column exist, compare row and column with data. If row and column do not exist, compare data with default.
|
||||
let lastRowNum = data.length;
|
||||
let lastColNum = data[0].length;
|
||||
if (row != null && column != null && row > 0 && column > 0) {
|
||||
@ -210,6 +211,7 @@ export function updateSheet(ctx: Context, newData: Sheet[]) {
|
||||
for (let i = 0; i < data.length; i += 1) {
|
||||
for (let j = 0; j < data[i].length; j += 1) {
|
||||
expandedData[i][j] = data[i][j];
|
||||
setFormulaCellInfo(ctx, { r: i, c: j, id: newDatum.id! }, data);
|
||||
}
|
||||
}
|
||||
newDatum.data = expandedData;
|
||||
@ -220,6 +222,14 @@ export function updateSheet(ctx: Context, newData: Sheet[]) {
|
||||
}
|
||||
} else if (newDatum.celldata != null) {
|
||||
initSheetData(ctx, index, newDatum);
|
||||
const _index = getSheetIndex(ctx, newDatum.id!) as number;
|
||||
newDatum.celldata?.forEach((d) => {
|
||||
setFormulaCellInfo(
|
||||
ctx,
|
||||
{ r: d.r, c: d.c, id: newDatum.id! },
|
||||
ctx.luckysheetfile[_index].data
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ import {
|
||||
import { showLinkCard } from "./hyperlink";
|
||||
import { cfSplitRange } from "./conditionalFormat";
|
||||
import { getCellTextInfo } from "./text";
|
||||
import { setFormulaObject } from "./formulaHelper";
|
||||
import { setFormulaCellInfo } from "./formulaHelper";
|
||||
|
||||
type ToolbarItemClickHandler = (
|
||||
ctx: Context,
|
||||
@ -903,7 +903,7 @@ export function autoSelectionFormula(
|
||||
if (!isfalse) {
|
||||
ctx.formulaCache.execFunctionExist.reverse();
|
||||
ctx.formulaCache.execFunctionExist.forEach((formulaCell) => {
|
||||
setFormulaObject(
|
||||
setFormulaCellInfo(
|
||||
ctx,
|
||||
{ r: formulaCell.r, c: formulaCell.c, id: ctx.currentSheetId },
|
||||
flowdata
|
||||
|
@ -314,3 +314,45 @@ export type GlobalCache = {
|
||||
|
||||
export type SingleRange = { row: number[]; column: number[] };
|
||||
export type Range = SingleRange[];
|
||||
|
||||
// FORMULA
|
||||
export type FormulaDependency = {
|
||||
row: [number, number];
|
||||
column: [number, number];
|
||||
sheetId: string | undefined;
|
||||
};
|
||||
|
||||
export type FormulaDependenciesMap = {
|
||||
[formula: string]: FormulaDependency[];
|
||||
};
|
||||
|
||||
type AncestorFormulaCell = {
|
||||
[rxcxix: string]: number;
|
||||
};
|
||||
|
||||
export type FormulaCellInfo = {
|
||||
formulaDependency: FormulaDependency[];
|
||||
calc_funcStr: string;
|
||||
key: string;
|
||||
r: number;
|
||||
c: number;
|
||||
id: string;
|
||||
parents: AncestorFormulaCell;
|
||||
chidren: AncestorFormulaCell;
|
||||
color: string;
|
||||
};
|
||||
|
||||
export type FormulaCellInfoMap = {
|
||||
[rxcxix: string]: FormulaCellInfo;
|
||||
};
|
||||
|
||||
export type FormulaCell = {
|
||||
r: number;
|
||||
c: number;
|
||||
id: string;
|
||||
parent?: AncestorFormulaCell;
|
||||
func?: [boolean, number, string];
|
||||
color?: string;
|
||||
chidren?: AncestorFormulaCell;
|
||||
times?: number;
|
||||
};
|
||||
|
@ -1,3 +1,4 @@
|
||||
import _ from "lodash";
|
||||
import {
|
||||
getDropdownList,
|
||||
getFlowdata,
|
||||
@ -83,12 +84,19 @@ const DataVerification: React.FC = () => {
|
||||
getSheetIndex(ctx, ctx.currentSheetId) as number
|
||||
].dataVerification ?? {};
|
||||
|
||||
const str = range[range.length - 1].row[0];
|
||||
const edr = range[range.length - 1].row[1];
|
||||
const stc = range[range.length - 1].column[0];
|
||||
const edc = range[range.length - 1].column[1];
|
||||
const str = range?.[range.length - 1]?.row[0];
|
||||
const edr = range?.[range.length - 1]?.row[1];
|
||||
const stc = range?.[range.length - 1]?.column[0];
|
||||
const edc = range?.[range.length - 1]?.column[1];
|
||||
const d = getFlowdata(ctx);
|
||||
if (!d) return;
|
||||
if (
|
||||
!d ||
|
||||
_.isNil(str) ||
|
||||
_.isNil(stc) ||
|
||||
_.isNil(edr) ||
|
||||
_.isNil(edc)
|
||||
)
|
||||
return;
|
||||
for (let r = str; r <= edr; r += 1) {
|
||||
for (let c = stc; c <= edc; c += 1) {
|
||||
const key = `${r}_${c}`;
|
||||
@ -116,10 +124,12 @@ const DataVerification: React.FC = () => {
|
||||
const currentDataVerification =
|
||||
ctx.luckysheetfile[getSheetIndex(ctx, ctx.currentSheetId) as number]
|
||||
.dataVerification ?? {};
|
||||
const str = range[range.length - 1].row[0];
|
||||
const edr = range[range.length - 1].row[1];
|
||||
const stc = range[range.length - 1].column[0];
|
||||
const edc = range[range.length - 1].column[1];
|
||||
const str = range?.[range.length - 1]?.row[0];
|
||||
const edr = range?.[range.length - 1]?.row[1];
|
||||
const stc = range?.[range.length - 1]?.column[0];
|
||||
const edc = range?.[range.length - 1]?.column[1];
|
||||
if (_.isNil(str) || _.isNil(stc) || _.isNil(edr) || _.isNil(edc))
|
||||
return;
|
||||
for (let r = str; r <= edr; r += 1) {
|
||||
for (let c = stc; c <= edc; c += 1) {
|
||||
delete currentDataVerification[`${r}_${c}`];
|
||||
|
@ -20,6 +20,7 @@ import {
|
||||
locale,
|
||||
calcSelectionInfo,
|
||||
groupValuesRefresh,
|
||||
setFormulaCellInfoMap,
|
||||
} from "@fortune-sheet/core";
|
||||
import React, {
|
||||
useMemo,
|
||||
@ -440,7 +441,12 @@ const Workbook = React.forwardRef<WorkbookInstance, Settings & AdditionalProps>(
|
||||
newData.forEach((newDatum) => {
|
||||
const index = getSheetIndex(draftCtx, newDatum.id!) as number;
|
||||
const sheet = draftCtx.luckysheetfile?.[index];
|
||||
initSheetData(draftCtx, sheet, index);
|
||||
const cellMatrixData = initSheetData(draftCtx, sheet, index);
|
||||
setFormulaCellInfoMap(
|
||||
draftCtx,
|
||||
sheet.calcChain,
|
||||
cellMatrixData || undefined
|
||||
);
|
||||
});
|
||||
}
|
||||
if (mergedSettings.devicePixelRatio > 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user