private static bool CalcOperandsAreNotTargetsOfOtherCalcs(CalcExpressionVm thisCalc, List<CalcExpressionVm> allCalcs) { return !thisCalc.Operands.Any(o => allCalcs.Any(cc2 => cc2.TargetGridCode == o.GridCode && cc2.TargetRowCode == o.RowCode &&cc2.TargetColCode == o.ColCode)); }
private static void EvaluateExpressionAndAssign(CalcExpressionVm calcVm, CellVm targetCell) { var expr = new CalcEngine.CalcEngine(); var result = (double)expr.Evaluate(calcVm.Expression); if (UpdateContextIsCellValue(calcVm.UpdateContext)) { targetCell.Value = FormatCellValue(result, targetCell); } else { FormatCellHoverAddition(result, targetCell); } }
private static void RunColCalcRecursive(CalcExpressionVm calcToRun, List<CalcExpressionVm> allColCalcs, RowVm row) { var expandedColCalc = ExpandColCalcForRow(calcToRun, row); var targetCell = row.Cells.FirstOrDefault(c => c.GridCode == expandedColCalc.TargetGridCode && c.RowCode == expandedColCalc.TargetRowCode && c.ColCode == expandedColCalc.TargetColCode); if (targetCell == null) return; EvaluateExpressionAndAssign(expandedColCalc, targetCell); if (!UpdateContextIsCellValue(calcToRun.UpdateContext)) return; var cascadedColCalcs = allColCalcs.Where(c => c.Operands.Any(o => o.GridCode == targetCell.GridCode && o.ColCode == targetCell.ColCode)).ToList(); if (cascadedColCalcs.Any()) { cascadedColCalcs.ForEach(cc => { RunColCalcRecursive(cc, allColCalcs, row); }); } }
private static void RunCellCalcRecursive(CalcExpressionVm calcToRun, List<CalcExpressionVm> allCellCalcs, ExhibitVm exhibit, List<CalcExpressionVm> allRowCalcs, List<CalcExpressionVm> allColCalcs) { foreach (var operand in calcToRun.Operands) { var grid = exhibit.Grids.FirstOrDefault(g => g.GridCode == operand.GridCode); var row = grid.Rows.FirstOrDefault(r => r.RowCode == operand.RowCode); var cell = row.Cells.FirstOrDefault(c => c.ColCode == operand.ColCode); var cellValue = GetCellValue(cell); var operandToken = GetCellToken(operand.GridCode, operand.RowCode, operand.ColCode); calcToRun.Expression = calcToRun.Expression.Replace(operandToken, cellValue.ToString(CultureInfo.CurrentCulture)); } var targetGrid = exhibit.Grids.FirstOrDefault(g => g.GridCode == calcToRun.TargetGridCode); var targetRow = targetGrid.Rows.FirstOrDefault(r => r.RowCode == calcToRun.TargetRowCode); var targetCell = targetRow.Cells.FirstOrDefault(c => c.ColCode == calcToRun.TargetColCode); EvaluateExpressionAndAssign(calcToRun, targetCell); if (!UpdateContextIsCellValue(calcToRun.UpdateContext)) return; //There may be some additional row/col calcs to be run now that we've updated a single cell RunAllRowAndColCalcsForCellRecursive(targetCell, allRowCalcs, allColCalcs, targetGrid); //Cascade var cascadedCellCalcs = allCellCalcs.Where(c => c.Operands.Any(o => o.GridCode == targetCell.GridCode && o.RowCode == targetCell.RowCode && o.ColCode == targetCell.ColCode)).ToList(); if (cascadedCellCalcs.Any()) { cascadedCellCalcs.ForEach(cc => { RunCellCalcRecursive(cc, allCellCalcs, exhibit, allRowCalcs, allColCalcs); }); } }
private static CalcExpressionVm ExpandColCalcForRow(CalcExpressionVm colCalc, RowVm row) { var calc = new CalcExpressionVm() { TargetGridCode = colCalc.TargetGridCode, TargetColCode = colCalc.TargetColCode, TargetRowCode = row.RowCode, Expression = colCalc.Expression.Split('.').Aggregate((c, n) => n == "" ? c + "." + row.RowCode + n : c + "." + n), UpdateContext = colCalc.UpdateContext, Operands = colCalc.Operands.Select(o => new CalcOperandVm() { GridCode = o.GridCode, ColCode = o.ColCode, RowCode = row.RowCode }).ToList() }; foreach (var operand in calc.Operands) { var cell = row.Cells.FirstOrDefault(c => c.GridCode == operand.GridCode && c.RowCode == operand.RowCode && c.ColCode == operand.ColCode); var cellValue = GetCellValue(cell); var operandToken = GetCellToken(operand.GridCode, operand.RowCode, operand.ColCode); calc.Expression = calc.Expression.Replace(operandToken, cellValue.ToString(CultureInfo.CurrentCulture)); } return calc; }