11import { compile } from "../../formulas" ;
2- import { deepCopy , deepEquals } from "../../helpers" ;
2+ import { deepCopy , deepEquals , getCanonicalSymbolName } from "../../helpers" ;
33import { createPivotFormula , getMaxObjectId } from "../../helpers/pivot/pivot_helpers" ;
44import { pivotRegistry } from "../../helpers/pivot/pivot_registry" ;
55import { SpreadsheetPivotTable } from "../../helpers/pivot/table_spreadsheet_pivot" ;
@@ -22,11 +22,16 @@ interface Pivot {
2222 formulaId : string ;
2323}
2424
25+ interface MeasureState {
26+ formula : RangeCompiledFormula ;
27+ fullDependencies : Range [ ] ;
28+ }
29+
2530interface CoreState {
2631 nextFormulaId : number ;
2732 pivots : Record < UID , Pivot | undefined > ;
2833 formulaIds : Record < UID , string | undefined > ;
29- compiledMeasureFormulas : Record < UID , Record < string , RangeCompiledFormula | undefined > > ;
34+ compiledMeasureFormulas : Record < UID , Record < string , MeasureState | undefined > > ;
3035}
3136
3237export class PivotCorePlugin extends CorePlugin < CoreState > implements CoreState {
@@ -39,14 +44,15 @@ export class PivotCorePlugin extends CorePlugin<CoreState> implements CoreState
3944 "getMeasureCompiledFormula" ,
4045 "getPivotName" ,
4146 "isExistingPivot" ,
47+ "getMeasureFullDependencies" ,
4248 ] as const ;
4349
4450 readonly nextFormulaId : number = 1 ;
4551 public readonly pivots : {
4652 [ pivotId : UID ] : Pivot | undefined ;
4753 } = { } ;
4854 public readonly formulaIds : { [ formulaId : UID ] : UID | undefined } = { } ;
49- public readonly compiledMeasureFormulas : Record < UID , Record < string , RangeCompiledFormula > > = { } ;
55+ public readonly compiledMeasureFormulas : Record < UID , Record < string , MeasureState > > = { } ;
5056
5157 allowDispatch ( cmd : CoreCommand ) {
5258 switch ( cmd . type ) {
@@ -126,7 +132,7 @@ export class PivotCorePlugin extends CorePlugin<CoreState> implements CoreState
126132 }
127133 case "UPDATE_PIVOT" : {
128134 this . history . update ( "pivots" , cmd . pivotId , "definition" , deepCopy ( cmd . pivot ) ) ;
129- this . compileCalculatedMeasures ( cmd . pivot . measures ) ;
135+ this . compileCalculatedMeasures ( cmd . pivotId , cmd . pivot . measures ) ;
130136 break ;
131137 }
132138 }
@@ -145,9 +151,15 @@ export class PivotCorePlugin extends CorePlugin<CoreState> implements CoreState
145151 this . history . update ( "pivots" , pivotId , "definition" , newDefinition ) ;
146152 }
147153 }
148- for ( const sheetId in this . compiledMeasureFormulas ) {
149- for ( const formulaString in this . compiledMeasureFormulas [ sheetId ] ) {
150- const compiledFormula = this . compiledMeasureFormulas [ sheetId ] [ formulaString ] ;
154+ for ( const pivotId in this . compiledMeasureFormulas ) {
155+ for ( const measureId in this . compiledMeasureFormulas [ pivotId ] ) {
156+ // const compiledFormula = this.compiledMeasureFormulas[sheetId][formulaString];
157+ const measure = this . pivots [ pivotId ] ?. definition . measures . find ( ( m ) => m . id === measureId ) ;
158+ if ( ! measure || ! measure . computedBy ) {
159+ continue ;
160+ }
161+ const sheetId = measure . computedBy . sheetId ;
162+ const compiledFormula = this . compiledMeasureFormulas [ pivotId ] [ measureId ] . formula ;
151163 const newDependencies : Range [ ] = [ ] ;
152164 for ( const range of compiledFormula . dependencies ) {
153165 const change = applyChange ( range ) ;
@@ -162,8 +174,9 @@ export class PivotCorePlugin extends CorePlugin<CoreState> implements CoreState
162174 compiledFormula . tokens ,
163175 newDependencies
164176 ) ;
165- if ( newFormulaString !== formulaString ) {
166- this . replaceMeasureFormula ( sheetId , formulaString , newFormulaString ) ;
177+ const oldFormulaString = measure . computedBy . formula ;
178+ if ( newFormulaString !== oldFormulaString ) {
179+ this . replaceMeasureFormula ( oldFormulaString , newFormulaString ) ;
167180 }
168181 }
169182 }
@@ -210,12 +223,18 @@ export class PivotCorePlugin extends CorePlugin<CoreState> implements CoreState
210223 return pivotId in this . pivots ;
211224 }
212225
213- getMeasureCompiledFormula ( measure : PivotCoreMeasure ) : RangeCompiledFormula {
226+ getMeasureCompiledFormula ( pivotId : UID , measure : PivotCoreMeasure ) : RangeCompiledFormula {
214227 if ( ! measure . computedBy ) {
215228 throw new Error ( `Measure ${ measure . fieldName } is not computed by formula` ) ;
216229 }
217- const sheetId = measure . computedBy . sheetId ;
218- return this . compiledMeasureFormulas [ sheetId ] [ measure . computedBy . formula ] ;
230+ return this . compiledMeasureFormulas [ pivotId ] [ measure . id ] . formula ;
231+ }
232+
233+ getMeasureFullDependencies ( pivotId : UID , measure : PivotCoreMeasure ) : Range [ ] {
234+ if ( ! measure . computedBy ) {
235+ throw new Error ( `Measure ${ measure . fieldName } is not computed by formula` ) ;
236+ }
237+ return this . compiledMeasureFormulas [ pivotId ] [ measure . id ] . fullDependencies ;
219238 }
220239
221240 // -------------------------------------------------------------------------
@@ -228,27 +247,73 @@ export class PivotCorePlugin extends CorePlugin<CoreState> implements CoreState
228247 formulaId = this . nextFormulaId . toString ( )
229248 ) {
230249 this . history . update ( "pivots" , pivotId , { definition : deepCopy ( pivot ) , formulaId } ) ;
231- this . compileCalculatedMeasures ( pivot . measures ) ;
250+ this . compileCalculatedMeasures ( pivotId , pivot . measures ) ;
232251 this . history . update ( "formulaIds" , formulaId , pivotId ) ;
233252 this . history . update ( "nextFormulaId" , this . nextFormulaId + 1 ) ;
234253 }
235254
236- private compileCalculatedMeasures ( measures : PivotCoreMeasure [ ] ) {
255+ private compileCalculatedMeasures ( pivotId : UID , measures : PivotCoreMeasure [ ] ) {
237256 for ( const measure of measures ) {
238257 if ( measure . computedBy ) {
239- const sheetId = measure . computedBy . sheetId ;
240258 const compiledFormula = this . compileMeasureFormula (
241259 measure . computedBy . sheetId ,
242260 measure . computedBy . formula
243261 ) ;
244262 this . history . update (
245263 "compiledMeasureFormulas" ,
246- sheetId ,
247- measure . computedBy . formula ,
264+ pivotId ,
265+ measure . id ,
266+ "formula" ,
248267 compiledFormula
249268 ) ;
250269 }
251270 }
271+ for ( const measure of measures ) {
272+ if ( measure . computedBy ) {
273+ const dependencies = this . computeMeasureFullDependencies ( pivotId , measure ) ;
274+ this . history . update (
275+ "compiledMeasureFormulas" ,
276+ pivotId ,
277+ measure . id ,
278+ "fullDependencies" ,
279+ dependencies
280+ ) ;
281+ }
282+ }
283+ }
284+
285+ private computeMeasureFullDependencies (
286+ pivotId : UID ,
287+ measure : PivotCoreMeasure ,
288+ exploredMeasures : Set < string > = new Set ( )
289+ ) : Range [ ] {
290+ const rangeList : Range [ ] = [ ] ;
291+ const definition = this . getPivotCoreDefinition ( pivotId ) ;
292+ const formula = this . getMeasureCompiledFormula ( pivotId , measure ) ;
293+ for ( const token of formula . tokens ) {
294+ if ( token . type !== "SYMBOL" ) {
295+ continue ;
296+ }
297+ const existingMeasure = definition . measures . find (
298+ ( measureCandidate ) =>
299+ getCanonicalSymbolName ( measureCandidate . id ) === token . value &&
300+ measure . id !== measureCandidate . id
301+ ) ;
302+
303+ if (
304+ ! existingMeasure ||
305+ exploredMeasures . has ( existingMeasure . id ) ||
306+ ! existingMeasure . computedBy
307+ )
308+ continue ;
309+
310+ rangeList . push (
311+ ...this . computeMeasureFullDependencies ( pivotId , existingMeasure , exploredMeasures )
312+ ) ;
313+ }
314+ rangeList . push ( ...formula . dependencies . filter ( ( range ) => ! range . invalidXc ) ) ;
315+ exploredMeasures . add ( measure . id ) ;
316+ return rangeList ;
252317 }
253318
254319 private insertPivot ( position : CellPosition , formulaId : UID , table : SpreadsheetPivotTable ) {
@@ -314,22 +379,23 @@ export class PivotCorePlugin extends CorePlugin<CoreState> implements CoreState
314379 } ;
315380 }
316381
317- private replaceMeasureFormula ( sheetId : UID , formulaString : string , newFormulaString : string ) {
318- this . history . update ( "compiledMeasureFormulas" , sheetId , formulaString , undefined ) ;
319- this . history . update (
320- "compiledMeasureFormulas" ,
321- sheetId ,
322- newFormulaString ,
323- this . compileMeasureFormula ( sheetId , newFormulaString )
324- ) ;
382+ private replaceMeasureFormula ( formulaString : string , newFormulaString : string ) {
383+ // this.history.update("compiledMeasureFormulas", sheetId, formulaString, undefined);
384+ // this.history.update(
385+ // "compiledMeasureFormulas",
386+ // sheetId,
387+ // newFormulaString,
388+ // this.compileMeasureFormula(sheetId, newFormulaString)
389+ // );
325390 for ( const pivotId in this . pivots ) {
326391 const pivot = this . pivots [ pivotId ] ;
327392 if ( ! pivot ) {
328393 continue ;
329394 }
330-
395+ let shouldUpdateMeasures = false ;
331396 for ( const measure of pivot . definition . measures ) {
332397 if ( measure . computedBy ?. formula === formulaString ) {
398+ shouldUpdateMeasures = true ;
333399 const measureIndex = pivot . definition . measures . indexOf ( measure ) ;
334400 this . history . update (
335401 "pivots" ,
@@ -338,10 +404,13 @@ export class PivotCorePlugin extends CorePlugin<CoreState> implements CoreState
338404 "measures" ,
339405 measureIndex ,
340406 "computedBy" ,
341- { formula : newFormulaString , sheetId }
407+ { formula : newFormulaString , sheetId : measure . computedBy . sheetId }
342408 ) ;
343409 }
344410 }
411+ if ( shouldUpdateMeasures ) {
412+ this . compileCalculatedMeasures ( pivotId , pivot . definition . measures ) ;
413+ }
345414 }
346415 }
347416
0 commit comments