Esempio n. 1
0
        /// <summary>
        /// Get the parent node of a node
        /// </summary>
        /// <remarks>
        /// This is an expensive operation, as the whole tree will be searched through
        /// </remarks>
        public static ParseTreeNode Parent(this ParseTreeNode child, ParseTreeNode treeRoot)
        {
            var parent = treeRoot.AllNodes()
                         .FirstOrDefault(node => node.ChildNodes.Any(c => c == child));

            if (parent == null)
            {
                throw new ArgumentException("Child is not part of the tree", nameof(child));
            }
            return(parent);
        }
Esempio n. 2
0
        public void SheetNamesWithSpacesCanBeExtractedCorrectly()
        {
            var strangeSheetNames = new[] { "\t", " ", "   ", " A", " ''A", " A ", " ''A1'' " };

            foreach (var sheetName in strangeSheetNames)
            {
                // Simple reference to another sheet
                var           sourceText = $"'{sheetName}'!A1";
                ParseTreeNode node       = ExcelFormulaParser.Parse(sourceText);

                var actual = node.AllNodes(GrammarNames.Prefix).First().GetPrefixInfo().Sheet;

                Assert.AreEqual(sheetName, actual);
            }
        }
Esempio n. 3
0
        private static IEnumerable <ParseTreeNode> CellContainedInRanges(ParseTreeNode fqcellref, ParseTreeNode formula, Context CtxF)
        {
            var cell = new Location(fqcellref.ChildNodes[1].Print());
            // Select all  references and qualify them
            var references = formula.GetReferenceNodes().Select(CtxF.Qualify).ToList();

            // Check the different types of ranges
            var ranges  = formula.AllNodes().Where(reference => reference.MatchFunction(":"));
            var rangesc = ranges.Where(range =>
            {
                var args  = range.GetFunctionArguments().Select(ExcelFormulaParser.Print).ToList();
                var start = new Location(args[0]);
                var end   = new Location(args[1]);
                return(cell.Row >= start.Row && cell.Row <= end.Row &&
                       cell.Column >= start.Column && cell.Column <= end.Column);
            });
            var vranges = references.Where(reference =>
                                           reference.ChildNodes[0].Is(GrammarNames.Prefix) &&
                                           reference.ChildNodes[1].Is(GrammarNames.VerticalRange)
                                           );
            var vrangesc = vranges.Where(reference =>
            {
                var vrange = reference.ChildNodes[1];
                var pieces = vrange.Print().Replace("$", "").Split(':');
                return(cell.Column >= AuxConverter.ColToInt(pieces[0]) &&
                       cell.Column <= AuxConverter.ColToInt(pieces[1]));
            });
            var hranges = references.Where(reference =>
                                           reference.ChildNodes[0].Is(GrammarNames.Prefix) &&
                                           reference.ChildNodes[1].Is(GrammarNames.HorizontalRange)
                                           );
            var hrangesc = hranges.Where(reference =>
            {
                var hrange = reference.ChildNodes[1];
                var pieces = hrange.Print().Replace("$", "").Split(':');
                return(cell.Row >= (int.Parse(pieces[0]) - 1) && cell.Row <= (int.Parse(pieces[1]) - 1));
            });
            var combined = new[] { rangesc, vrangesc, hrangesc }.SelectMany(x => x);

            return(combined);
        }
Esempio n. 4
0
        private static bool NodeCanBeGrouped(ParseTreeNode node)
        {
            // can be grouped if the node is a reference
            var relevant = node.SkipToRelevant();

            return(relevant.Is(GrammarNames.Reference)
                   // And it's not
                   && !node.AllNodes().Any(childnode =>
                                           // named ranges
                                           childnode.Is(GrammarNames.NamedRange)
                                           // vertical or horizontal ranges
                                           || childnode.Is(GrammarNames.HorizontalRange) ||
                                           childnode.Is(GrammarNames.VerticalRange)
                                           // structured references
                                           || childnode.Is(GrammarNames.StructureReference)
                                           // Error
                                           || childnode.Is(GrammarNames.RefError)
                                           // Reference Functions
                                           || childnode.IsFunction()
                                           ));
        }
Esempio n. 5
0
        public override ParseTreeNode Refactor(ParseTreeNode applyto)
        {
            if (excel == null)
            {
                throw new InvalidOperationException("Must have reference to Excel worksheet to group references");
            }
            var targetFunctions = applyto.AllNodes()
                                  .Where(IsTargetFunction)
                                  .ToList();

            foreach (var function in targetFunctions)
            {
                var arguments = function.GetFunctionArguments().Select(node => node.SkipToRelevant()).ToList();
                var unions    = arguments
                                .Select(arg => arg.ChildNodes.Count > 0 ? arg.ChildNodes[0] : arg)
                                .Where(ExcelFormulaParser.IsUnion);

                // Group Union arguments
                foreach (var fcall in unions)
                {
                    var args    = fcall.GetFunctionArguments().ToList();
                    var union   = fcall.ChildNodes[0];
                    var newargs = GroupReferenceList(args);
                    union.ChildNodes.Clear();
                    union.ChildNodes.AddRange(newargs);
                }

                // If this is a varags function group all arguments
                if (varargsFunctions.Contains(function.GetFunction()))
                {
                    var newargs = GroupReferenceList(arguments).ToList();
                    function.ChildNodes[1].ChildNodes.Clear();
                    function.ChildNodes[1].ChildNodes.AddRange(newargs);
                }
            }

            return(applyto);
        }
Esempio n. 6
0
 public override bool CanRefactor(ParseTreeNode applyto)
 {
     return(applyto.AllNodes().Any(IsTargetFunction));
 }
Esempio n. 7
0
 /// <summary>
 /// All non-terminal nodes of a certain type in depth-first pre-order
 /// </summary>
 public static IEnumerable <ParseTreeNode> AllNodes(this ParseTreeNode root, string type)
 {
     return(AllNodes(root.AllNodes(), type));
 }
Esempio n. 8
0
 /// <summary>
 /// Whether this tree contains any nodes of a type
 /// </summary>
 public static bool Contains(this ParseTreeNode root, string type)
 {
     return(root.AllNodes(type).Any());
 }
Esempio n. 9
0
 /// <summary>
 /// Get the parent node of a node
 /// </summary>
 /// <remarks>
 /// This is an expensive operation, as the whole tree will be searched through
 /// </remarks>
 public static ParseTreeNode Parent(this ParseTreeNode child, ParseTreeNode treeRoot)
 {
     var parent = treeRoot.AllNodes()
         .FirstOrDefault(node => node.ChildNodes.Any(c => c == child));
     if(parent == null) throw new ArgumentException("Child is not part of the tree", nameof(child));
     return parent;
 }