// Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ExcelFormula { public class ParseFormula { ExcelFormula parser; public ParseFormula(string formula) { parser = new ExcelFormula(formula, Console.Out); bool parserResult = false; try { parserResult = parser.Formula(); } catch (Peg.Base.PegException) { } if (!parserResult) { parser.Warning("Error processing " + formula); } } public string ReplaceSheetName(string oldName, string newName) { StringBuilder text = new StringBuilder(parser.GetSource()); ReplaceNode(parser.GetRoot(), (int)EExcelFormula.SheetName, oldName, newName, text); return text.ToString(); } public string ReplaceRelativeCell(int rowOffset, int colOffset) { StringBuilder text = new StringBuilder(parser.GetSource()); ReplaceRelativeCell(parser.GetRoot(), rowOffset, colOffset, text); return text.ToString(); } // Recursive function that will replace values from last to first private void ReplaceNode(Peg.Base.PegNode node, int id, string oldName, string newName, StringBuilder text) { if (node.next_ != null) ReplaceNode(node.next_, id, oldName, newName, text); if (node.id_ == id && parser.GetSource().Substring(node.match_.posBeg_, node.match_.Length) == oldName) { text.Remove(node.match_.posBeg_, node.match_.Length); text.Insert(node.match_.posBeg_, newName); } else if (node.child_ != null) ReplaceNode(node.child_, id, oldName, newName, text); } // Recursive function that will adjust relative cells from last to first private void ReplaceRelativeCell(Peg.Base.PegNode node, int rowOffset, int colOffset, StringBuilder text) { if (node.next_ != null) ReplaceRelativeCell(node.next_, rowOffset, colOffset, text); if (node.id_ == (int)EExcelFormula.A1Row && parser.GetSource().Substring(node.match_.posBeg_, 1) != "$") { int rowNumber = Convert.ToInt32(parser.GetSource().Substring(node.match_.posBeg_, node.match_.Length)); text.Remove(node.match_.posBeg_, node.match_.Length); text.Insert(node.match_.posBeg_, Convert.ToString(rowNumber + rowOffset)); } else if (node.id_ == (int)EExcelFormula.A1Column && parser.GetSource().Substring(node.match_.posBeg_, 1) != "$") { int colNumber = GetColumnNumber(parser.GetSource().Substring(node.match_.posBeg_, node.match_.Length)); text.Remove(node.match_.posBeg_, node.match_.Length); text.Insert(node.match_.posBeg_, GetColumnId(colNumber + colOffset)); } else if (node.child_ != null) ReplaceRelativeCell(node.child_, rowOffset, colOffset, text); } // Converts the column reference string to a column number (e.g. A -> 1, B -> 2) private static int GetColumnNumber(string cellReference) { int columnNumber = 0; foreach (char c in cellReference) { if (Char.IsLetter(c)) columnNumber = columnNumber * 26 + System.Convert.ToInt32(c) - System.Convert.ToInt32('A') + 1; } return columnNumber; } // Translates the column number to the column reference string (e.g. 1 -> A, 2-> B) private static string GetColumnId(int columnNumber) { string result = ""; do { result = ((char)((columnNumber - 1) % 26 + (int)'A')).ToString() + result; columnNumber = (columnNumber - 1) / 26; } while (columnNumber != 0); return result; } } }