export class Sum { ColumnIndex: number; Original: number; Adjustment: number; FromParents: number; FromChildren: number; FromOutside: number; constructor() { this.ColumnIndex = 0; } } export class Table { Name: string; Rows: Array>; Parent?: Table; Children: Array; constructor(inName: string, inRows: Array>) { this.Name = inName; this.Rows = inRows; this.Parent = null; this.Children = []; } Pivot(inColumn: number) { var cell: string; var child: Table; var context: Table; context = this; this.Rows.forEach((inRow: Array)=> { cell = inRow[inColumn]; child = this.Children.find( (inChild: Table) => inChild.Name == cell ); if(!child) { child = new Table(cell, []); child.Parent = context; context.Children.push(child); } child.Rows.push(inRow); }); this.Rows = []; } PivotTree(inColumns: Array) { var columns: Array; if(inColumns.length == 0) { return; } columns = [...inColumns]; this.Pivot(columns.shift()); this.Children.forEach( (inChild: Table) => { inChild.PivotTree(columns); }); } ItrParents(inFunction: Function) { if(this.Parent) { inFunction(this.Parent); this.Parent.ItrParents(inFunction); } } ItrChildren(inFunction: Function) { this.Children.forEach( (inChild: Table) => { inFunction(inChild); inChild.ItrChildren(inFunction); }); } ItrLeaves(inFunction:Function) { if(this.Children.length == 0) { inFunction(this); } else { this.Children.forEach( (inChild: Table) => inChild.ItrLeaves(inFunction) ); } } }