using System; using System.Collections.Generic; using System.Text; namespace CPF.ReoGrid.Formula { internal class FormulaRefactor { internal static string Generate(string input, STNode node) { return FormulaRefactor.Generate(input, node, FormulaFormatFlag.Default); } internal static string Generate(string input, STNode node, FormulaFormatFlag flag) { StringBuilder stringBuilder = new StringBuilder(); FormulaRefactor.GenerateExpression(stringBuilder, input, node, flag); bool flag2 = stringBuilder[stringBuilder.Length - 1] == ' '; if (flag2) { stringBuilder.Remove(stringBuilder.Length - 1, 1); } return stringBuilder.ToString(); } private static void GenerateExpression(StringBuilder sb, string input, STNode node, FormulaFormatFlag flag) { switch (node.Type) { case STNodeType.CONNECT: FormulaRefactor.GenerateOperatorString(sb, input, "&", node, flag); break; default: sb.Append(node.ToString()); break; case STNodeType.NUMBER: sb.Append(((STNumberNode)node).Value); break; case STNodeType.STRING: sb.Append(((STStringNode)node).Text); break; case STNodeType.IDENTIFIER: sb.Append(((STIdentifierNode)node).Identifier); break; case STNodeType.RANGE: sb.Append(((STRangeNode)node).Range.ToAddress()); break; case STNodeType.CELL: sb.Append(((STCellNode)node).Position.ToAddress()); break; case STNodeType.FUNCTION_CALL: { STFunctionNode stfunctionNode = (STFunctionNode)node; string name = stfunctionNode.Name; bool flag2 = (flag & FormulaFormatFlag.FunctionNameAutoUppercase) == FormulaFormatFlag.FunctionNameAutoUppercase; if (flag2) { sb.Append(name.ToUpper()); } else { sb.Append(name); } FormulaRefactor.AddSpaceIfFlag(sb, flag, FormulaFormatFlag.SpaceAfterFunctionName); sb.Append('('); FormulaRefactor.AddSpaceIfFlag(sb, flag, FormulaFormatFlag.SpaceBeforeParameterList); for (int i = 0; i < node.Children.Count; i++) { bool flag3 = i > 0; if (flag3) { FormulaRefactor.AddSpaceIfFlag(sb, flag, FormulaFormatFlag.SpaceBeforeComma); sb.Append(','); FormulaRefactor.AddSpaceIfFlag(sb, flag, FormulaFormatFlag.SpaceAfterComma); } FormulaRefactor.GenerateExpression(sb, input, node.Children[i], flag); } FormulaRefactor.AddSpaceIfFlag(sb, flag, FormulaFormatFlag.SpaceAfterParameterList); sb.Append(')'); break; } case STNodeType.ADD: FormulaRefactor.GenerateOperatorString(sb, input, "+", node, flag); break; case STNodeType.SUB: FormulaRefactor.GenerateOperatorString(sb, input, "-", node, flag); break; case STNodeType.MUL: FormulaRefactor.GenerateOperatorString(sb, input, "*", node, flag); break; case STNodeType.DIV: FormulaRefactor.GenerateOperatorString(sb, input, "/", node, flag); break; case STNodeType.POW: FormulaRefactor.GenerateOperatorString(sb, input, "^", node, flag); break; case STNodeType.EQUALS: FormulaRefactor.GenerateOperatorString(sb, input, "=", node, flag); break; case STNodeType.GREAT_THAN: FormulaRefactor.GenerateOperatorString(sb, input, ">", node, flag); break; case STNodeType.LESS_THAN: FormulaRefactor.GenerateOperatorString(sb, input, "<", node, flag); break; case STNodeType.GREAT_EQUALS: FormulaRefactor.GenerateOperatorString(sb, input, ">=", node, flag); break; case STNodeType.LESS_EQUALS: FormulaRefactor.GenerateOperatorString(sb, input, "<=", node, flag); break; case STNodeType.UNARY_MINUS: sb.Append('-'); FormulaRefactor.AddSpaceIfFlag(sb, flag, FormulaFormatFlag.SpaceAfterMinus); FormulaRefactor.GenerateExpression(sb, input, node.Children[0], flag); break; case STNodeType.UNARY_PERCENT: FormulaRefactor.GenerateExpression(sb, input, node.Children[0], flag); FormulaRefactor.AddSpaceIfFlag(sb, flag, FormulaFormatFlag.SpaceBeforePercent); sb.Append('%'); break; case STNodeType.SUB_EXPR: sb.Append('('); FormulaRefactor.AddSpaceIfFlag(sb, flag, FormulaFormatFlag.SpaceBeforeSubExpression); FormulaRefactor.GenerateExpression(sb, input, node.Children[0], flag); FormulaRefactor.AddSpaceIfFlag(sb, flag, FormulaFormatFlag.SpaceAfterSubExpression); sb.Append(')'); break; } } private static void AddSpaceIfFlag(StringBuilder sb, FormulaFormatFlag flag, FormulaFormatFlag target) { bool flag2 = (flag & target) == target && (sb.Length == 0 || sb[sb.Length - 1] != ' '); if (flag2) { sb.Append(' '); } } private static void GenerateOperatorString(StringBuilder sb, string input, string op, STNode node, FormulaFormatFlag flag) { STNode node2 = node.Children[0]; STNode node3 = node.Children[1]; FormulaRefactor.GenerateExpression(sb, input, node2, flag); bool flag2 = (flag & FormulaFormatFlag.SpaceBeforeOperator) == FormulaFormatFlag.SpaceBeforeOperator; if (flag2) { sb.Append(' '); } sb.Append(op); bool flag3 = (flag & FormulaFormatFlag.SpaceAfterOperator) == FormulaFormatFlag.SpaceAfterOperator; if (flag3) { sb.Append(' '); } FormulaRefactor.GenerateExpression(sb, input, node3, flag); } internal static void Reuse(Worksheet sheet, CellPosition fromPosition, RangePosition toRange) { fromPosition = sheet.FixPos(fromPosition); toRange = sheet.FixRange(toRange); Cell cell = sheet.cells[fromPosition.Row, fromPosition.Col]; bool flag = cell == null || string.IsNullOrEmpty(cell.InnerFormula) || cell.FormulaTree == null; if (flag) { throw new InvalidOperationException("cannot found formula from specified position, try reset formula for the cell again"); } bool flag2 = cell.formulaStatus > FormulaStatus.Normal; if (flag2) { throw new InvalidOperationException("formula in specified cell contains errors, correct the formula firstly"); } bool flag3 = toRange.Contains(fromPosition); if (flag3) { throw new ArgumentException("toRange should not contain the position of the formula to be reused"); } ReplacableString rs = new ReplacableString(cell.InnerFormula); STNode formulaTree = cell.FormulaTree; Stack> dirtyCells = new Stack>(); for (int i = toRange.Row; i <= toRange.EndRow; i++) { int j = toRange.Col; while (j <= toRange.EndCol) { Cell cell2 = sheet.CreateAndGetCell(i, j); bool flag4 = cell2.Colspan <= 0; if (flag4) { j++; } else { FormulaRefactor.CopyFormula(fromPosition, formulaTree, cell2, rs, dirtyCells); j += (int)cell.Colspan; } } } } internal static void CopyFormula(CellPosition fromPosition, STNode fromNode, Cell toCell, ReplacableString rs, Stack> dirtyCells) { Worksheet sheet = toCell.Worksheet; STNode node = (STNode)fromNode.Clone(); int r = toCell.Row; int c = toCell.Column; rs.Restore(); STNode.RecursivelyIterate(node, delegate(STNode n) { STNodeType type = n.Type; STNodeType stnodeType = type; if (stnodeType != STNodeType.RANGE) { if (stnodeType == STNodeType.CELL) { STCellNode stcellNode = (STCellNode)n; CellPosition position = stcellNode.Position; bool flag2 = position.RowProperty == PositionProperty.Relative; if (flag2) { position.Row += r - fromPosition.Row; } bool flag3 = position.ColumnProperty == PositionProperty.Relative; if (flag3) { position.Col += c - fromPosition.Col; } bool flag4 = position.Row < 0 || position.Col < 0 || position.Row >= sheet.rows.Count || position.Col >= sheet.cols.Count; if (flag4) { toCell.formulaStatus = FormulaStatus.InvalidReference; } stcellNode.Position = position; n.Start += rs.Offset; int num = rs.Replace(n.Start, n.Length, position.ToAddress()); n.Length += num; } } else { STRangeNode strangeNode = (STRangeNode)n; RangePosition range = strangeNode.Range; int num2 = r - fromPosition.Row; int num3 = c - fromPosition.Col; bool flag5 = range.StartRowProperty == PositionProperty.Relative; if (flag5) { range.Row += num2; } bool flag6 = range.StartColumnProperty == PositionProperty.Relative; if (flag6) { range.Col += num3; } bool flag7 = range.Row < 0 || range.Col < 0 || range.Row >= sheet.rows.Count || range.Col >= sheet.cols.Count || range.EndRow < 0 || range.EndCol < 0 || range.EndRow >= sheet.rows.Count || range.EndCol >= sheet.cols.Count; if (flag7) { toCell.formulaStatus = FormulaStatus.InvalidReference; } strangeNode.Range = range; n.Start += rs.Offset; int num4 = rs.Replace(n.Start, n.Length, range.ToAddress()); n.Length += num4; } }); toCell.InnerFormula = rs.ToString(); sheet.SetCellFormula(toCell, node); bool flag = toCell.formulaStatus == FormulaStatus.Normal; if (flag) { sheet.RecalcCell(toCell, dirtyCells); } } } }