Exemplo n.º 1
0
        /// <summary>
        /// Gets the ParserReferences from the input parse tree node and its children
        /// </summary>
        /// <remarks>
        /// 5 cases:
        /// 1. ReferenceItem node: convert to ParserReference
        /// 2. Reference node (Prefix ReferenceItem): convert to ParserReference, recursive call on the nodes returned from GetReferenceNodes(node)
        ///     (to include the references in the arguments of external UDFs)
        /// 3. Range node (Cell:Cell): recursive call to retrieve the 2 limits, create ParserReference of type CellRange
        /// 4. Range node with complex limits: recursive call to retrieve limits as 2 ParserReferences
        /// 5. Other cases (RefFunctionCall, Union, Arguments):recursive call on the nodes returned from GetReferenceNodes(node)
        /// </remarks>
        public static IEnumerable <ParserReference> GetParserReferences(this ParseTreeNode node)
        {
            if (node.Type() == GrammarNames.Reference && node.ChildNodes.Count == 1)
            {
                node = node.ChildNodes[0];
            }

            var list = new List <ParserReference>();

            switch (node.Type())
            {
            case GrammarNames.Cell:
            case GrammarNames.NamedRange:
            case GrammarNames.HorizontalRange:
            case GrammarNames.VerticalRange:
            case GrammarNames.StructuredReference:
                list.Add(new ParserReference(node));
                break;

            case GrammarNames.Reference:
                list.Add(new ParserReference(node));
                list.AddRange(node.ChildNodes[1].GetReferenceNodes().SelectMany(x => x.GetParserReferences()));
                break;

            default:
                if (node.IsRange())
                {
                    var rangeStart = GetParserReferences(node.ChildNodes[0].SkipToRelevant()).ToArray();
                    var rangeEnd   = GetParserReferences(node.ChildNodes[2].SkipToRelevant()).ToArray();
                    if (IsCellReference(rangeStart) && IsCellReference(rangeEnd))
                    {
                        ParserReference range = rangeStart.First();
                        range.MaxLocation    = rangeEnd.First().MinLocation;
                        range.ReferenceType  = ReferenceType.CellRange;
                        range.LocationString = node.Print();
                        list.Add(range);
                    }
                    else
                    {
                        list.AddRange(rangeStart);
                        list.AddRange(rangeEnd);
                    }
                }
                else
                {
                    list.AddRange(node.GetReferenceNodes().SelectMany(x => x.GetParserReferences()));
                }
                break;
            }
            return(list);
        }
Exemplo n.º 2
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);
        }