SSFormula.cs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. // Copyright (c) Microsoft. All rights reserved.
  2. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Text;
  7. namespace ExcelFormula
  8. {
  9. public class ParseFormula
  10. {
  11. ExcelFormula parser;
  12. public ParseFormula(string formula)
  13. {
  14. parser = new ExcelFormula(formula, Console.Out);
  15. bool parserResult = false;
  16. try
  17. {
  18. parserResult = parser.Formula();
  19. }
  20. catch (Peg.Base.PegException)
  21. {
  22. }
  23. if (!parserResult)
  24. {
  25. parser.Warning("Error processing " + formula);
  26. }
  27. }
  28. public string ReplaceSheetName(string oldName, string newName)
  29. {
  30. StringBuilder text = new StringBuilder(parser.GetSource());
  31. ReplaceNode(parser.GetRoot(), (int)EExcelFormula.SheetName, oldName, newName, text);
  32. return text.ToString();
  33. }
  34. public string ReplaceRelativeCell(int rowOffset, int colOffset)
  35. {
  36. StringBuilder text = new StringBuilder(parser.GetSource());
  37. ReplaceRelativeCell(parser.GetRoot(), rowOffset, colOffset, text);
  38. return text.ToString();
  39. }
  40. // Recursive function that will replace values from last to first
  41. private void ReplaceNode(Peg.Base.PegNode node, int id, string oldName, string newName, StringBuilder text)
  42. {
  43. if (node.next_ != null)
  44. ReplaceNode(node.next_, id, oldName, newName, text);
  45. if (node.id_ == id && parser.GetSource().Substring(node.match_.posBeg_, node.match_.Length) == oldName)
  46. {
  47. text.Remove(node.match_.posBeg_, node.match_.Length);
  48. text.Insert(node.match_.posBeg_, newName);
  49. }
  50. else if (node.child_ != null)
  51. ReplaceNode(node.child_, id, oldName, newName, text);
  52. }
  53. // Recursive function that will adjust relative cells from last to first
  54. private void ReplaceRelativeCell(Peg.Base.PegNode node, int rowOffset, int colOffset, StringBuilder text)
  55. {
  56. if (node.next_ != null)
  57. ReplaceRelativeCell(node.next_, rowOffset, colOffset, text);
  58. if (node.id_ == (int)EExcelFormula.A1Row && parser.GetSource().Substring(node.match_.posBeg_, 1) != "$")
  59. {
  60. int rowNumber = Convert.ToInt32(parser.GetSource().Substring(node.match_.posBeg_, node.match_.Length));
  61. text.Remove(node.match_.posBeg_, node.match_.Length);
  62. text.Insert(node.match_.posBeg_, Convert.ToString(rowNumber + rowOffset));
  63. }
  64. else if (node.id_ == (int)EExcelFormula.A1Column && parser.GetSource().Substring(node.match_.posBeg_, 1) != "$")
  65. {
  66. int colNumber = GetColumnNumber(parser.GetSource().Substring(node.match_.posBeg_, node.match_.Length));
  67. text.Remove(node.match_.posBeg_, node.match_.Length);
  68. text.Insert(node.match_.posBeg_, GetColumnId(colNumber + colOffset));
  69. }
  70. else if (node.child_ != null)
  71. ReplaceRelativeCell(node.child_, rowOffset, colOffset, text);
  72. }
  73. // Converts the column reference string to a column number (e.g. A -> 1, B -> 2)
  74. private static int GetColumnNumber(string cellReference)
  75. {
  76. int columnNumber = 0;
  77. foreach (char c in cellReference)
  78. {
  79. if (Char.IsLetter(c))
  80. columnNumber = columnNumber * 26 + System.Convert.ToInt32(c) - System.Convert.ToInt32('A') + 1;
  81. }
  82. return columnNumber;
  83. }
  84. // Translates the column number to the column reference string (e.g. 1 -> A, 2-> B)
  85. private static string GetColumnId(int columnNumber)
  86. {
  87. string result = "";
  88. do
  89. {
  90. result = ((char)((columnNumber - 1) % 26 + (int)'A')).ToString() + result;
  91. columnNumber = (columnNumber - 1) / 26;
  92. } while (columnNumber != 0);
  93. return result;
  94. }
  95. }
  96. }