Example #1
0
        private void RunGroupsSetGroups(Report rpt, WorkClass wc, List <GroupEntry> groupEntries)
        {
            // set the group entry value
            GroupEntry ge = groupEntries[0];

            wc.Data.CurrentGroups[ge.Group.GetIndex(rpt)] = ge;

            if (ge.NestedGroup.Count > 0)
            {
                RunGroupsSetGroups(rpt, wc, ge.NestedGroup);
            }
        }
        Rows GetNestedData(Report rpt, Row row)
        {
            if (row == null)
            {
                return(null);
            }

            ReportLink rl = this.Parent;

            while (rl != null)
            {
                if (rl is TableGroup || rl is List || rl is MatrixCell)
                {
                    break;
                }
                rl = rl.Parent;
            }
            if (rl == null)
            {
                return(null);                                   // should have been caught as an error
            }
            Grouping g = null;

            if (rl is TableGroup)
            {
                TableGroup tg = rl as TableGroup;
                g = tg.Grouping;
            }
            else if (rl is List)
            {
                List l = rl as List;
                g = l.Grouping;
            }
            else if (rl is MatrixCell)
            {
                MatrixCellEntry mce = this.GetMC(rpt);
                return(new Rows(rpt, mce.Data));
            }
            if (g == null)
            {
                return(null);
            }

            GroupEntry ge = row.R.CurrentGroups[g.GetIndex(rpt)];

            return(new Rows(rpt, row.R, ge.StartRow, ge.EndRow, null));
        }
Example #3
0
        private float RunGroupsFooterHeight(Pages pgs, TableWorkClass wc, GroupEntry ge)
        {
            Grouping g = ge.Group;

            if (g == null)
            {
                return(0);
            }

            TableGroup tg = g.Parent as TableGroup;                     // detail groups will result in null

            if (tg == null || tg.Footer == null)
            {
                return(0);
            }

            return(tg.Footer.HeightOfRows(pgs, wc.Data.Data[ge.EndRow]));
        }
Example #4
0
        private void SortGroups(Report rpt, List <GroupEntry> groupEntries, TableWorkClass wc)
        {
            GroupEntry fge = (GroupEntry)(groupEntries[0]);

            if (fge.Sort != null)
            {
                GroupEntryCompare gec = new GroupEntryCompare(rpt, wc);
                RunGroupsSetGroups(rpt, wc, groupEntries);
                groupEntries.Sort(gec);
            }

            // drill down into nested groups
            foreach (GroupEntry ge in groupEntries)
            {
                if (ge.NestedGroup.Count > 0)
                {
                    SortGroups(rpt, ge.NestedGroup, wc);
                }
            }
        }
Example #5
0
        private void RunSetGrouping(Report rpt, WorkClass wc)
        {
            GroupEntry[] currentGroups;

            // We have some data
            if (_Grouping != null ||
                _Sorting != null)                               // fix up the data
            {
                Rows saveData = wc.Data;
                wc.Data      = new Rows(rpt, null, _Grouping, _Sorting);
                wc.Data.Data = saveData.Data;
                wc.Data.Sort();
                PrepGroups(rpt, wc);
            }
            // If we haven't formed any groups then form one with all rows
            if (wc.Groups == null)
            {
                wc.Groups = new List <GroupEntry>();
                GroupEntry ge = new GroupEntry(null, null, 0);
                if (wc.Data.Data != null)                               // Do we have any data?
                {
                    ge.EndRow = wc.Data.Data.Count - 1;                 // yes
                }
                else
                {
                    ge.EndRow = -1;                                     // no
                }
                wc.Groups.Add(ge);                                      // top group
                currentGroups = new GroupEntry[1];
            }
            else
            {
                currentGroups = new GroupEntry[1];
            }

            wc.Data.CurrentGroups = currentGroups;

            return;
        }
Example #6
0
        private void PrepGroups(Report rpt, WorkClass wc)
        {
            if (_Grouping == null)
            {
                return;
            }

            int i = 0;
            // 1) Build array of all GroupExpression objects
            List <GroupExpression> gea = _Grouping.GroupExpressions.Items;

            GroupEntry[] currentGroups = new GroupEntry[1];
            _Grouping.SetIndex(rpt, 0);                 // set the index of this group (so we can find the GroupEntry)
            currentGroups[0] = new GroupEntry(_Grouping, _Sorting, 0);

            // Save the typecodes, and grouping by groupexpression; for later use
            TypeCode[] tcs = new TypeCode[gea.Count];
            Grouping[] grp = new Grouping[gea.Count];
            i = 0;
            foreach (GroupExpression ge in gea)
            {
                grp[i]   = (Grouping)(ge.Parent.Parent);                // remember the group
                tcs[i++] = ge.Expression.GetTypeCode();                 // remember type of expression
            }

            // 2) Loop thru the data, then loop thru the GroupExpression list
            wc.Groups = new List <GroupEntry>();
            object[] savValues  = null;
            object[] grpValues  = null;
            int      rowCurrent = 0;

            foreach (Row row in wc.Data.Data)
            {
                // Get the values for all the group expressions
                if (grpValues == null)
                {
                    grpValues = new object[gea.Count];
                }

                i = 0;
                foreach (GroupExpression ge in gea)                  // Could optimize to only calculate as needed in comparison loop below??
                {
                    grpValues[i++] = ge.Expression.Evaluate(rpt, row);
                }

                // For first row we just primed the pump; action starts on next row
                if (rowCurrent == 0)                                    // always start new group on first row
                {
                    rowCurrent++;
                    savValues = grpValues;
                    grpValues = null;
                    continue;
                }

                // compare the values; if change then we have a group break
                for (i = 0; i < savValues.Length; i++)
                {
                    if (Filter.ApplyCompare(tcs[i], savValues[i], grpValues[i]) != 0)
                    {
                        // start a new group; and force a break on every subgroup
                        GroupEntry saveGe = null;
                        for (int j = grp[i].GetIndex(rpt); j < currentGroups.Length; j++)
                        {
                            currentGroups[j].EndRow = rowCurrent - 1;
                            if (j == 0)
                            {
                                wc.Groups.Add(currentGroups[j]);                                                // top group
                            }
                            else if (saveGe == null)
                            {
                                currentGroups[j - 1].NestedGroup.Add(currentGroups[j]);
                            }
                            else
                            {
                                saveGe.NestedGroup.Add(currentGroups[j]);
                            }

                            saveGe           = currentGroups[j];                        // retain this GroupEntry
                            currentGroups[j] = new GroupEntry(currentGroups[j].Group, currentGroups[j].Sort, rowCurrent);
                        }
                        savValues = grpValues;
                        grpValues = null;
                        break;                                  // break out of the value comparison loop
                    }
                }
                rowCurrent++;
            }

            // End of all rows force break on end of rows
            for (i = 0; i < currentGroups.Length; i++)
            {
                currentGroups[i].EndRow = rowCurrent - 1;
                if (i == 0)
                {
                    wc.Groups.Add(currentGroups[i]);                                    // top group
                }
                else
                {
                    currentGroups[i - 1].NestedGroup.Add(currentGroups[i]);
                }
            }
            return;
        }
Example #7
0
		private void PrepGroups(Report rpt, WorkClass wc)
		{
			if (_Grouping == null)
				return;

			int i=0;
			// 1) Build array of all GroupExpression objects
			List<GroupExpression> gea = _Grouping.GroupExpressions.Items;
			GroupEntry[] currentGroups = new GroupEntry[1];
			_Grouping.SetIndex(rpt, 0);	// set the index of this group (so we can find the GroupEntry)
			currentGroups[0] = new GroupEntry(_Grouping, _Sorting, 0);

			// Save the typecodes, and grouping by groupexpression; for later use
			TypeCode[] tcs = new TypeCode[gea.Count];
			Grouping[] grp = new Grouping[gea.Count];
			i=0;
			foreach (GroupExpression ge in gea)
			{
				grp[i] = (Grouping) (ge.Parent.Parent);			// remember the group
				tcs[i++] = ge.Expression.GetTypeCode();	// remember type of expression
			}

			// 2) Loop thru the data, then loop thru the GroupExpression list
			wc.Groups = new List<GroupEntry>();
			object[] savValues=null;
			object[] grpValues=null;
			int rowCurrent = 0;

			foreach (Row row in wc.Data.Data)
			{
				// Get the values for all the group expressions
				if (grpValues == null)
					grpValues = new object[gea.Count];

				i=0;
				foreach (GroupExpression ge in gea)  // Could optimize to only calculate as needed in comparison loop below??
				{
					grpValues[i++] = ge.Expression.Evaluate(rpt, row);
				}

				// For first row we just primed the pump; action starts on next row
				if (rowCurrent == 0)			// always start new group on first row
				{
					rowCurrent++;
					savValues = grpValues;
					grpValues = null;
					continue;
				}

				// compare the values; if change then we have a group break
				for (i = 0; i < savValues.Length; i++)
				{
					if (Filter.ApplyCompare(tcs[i], savValues[i], grpValues[i]) != 0)
					{
						// start a new group; and force a break on every subgroup
						GroupEntry saveGe=null;	
						for (int j = grp[i].GetIndex(rpt); j < currentGroups.Length; j++)
						{
							currentGroups[j].EndRow = rowCurrent-1;
							if (j == 0)
								wc.Groups.Add(currentGroups[j]);		// top group
							else if (saveGe == null)
								currentGroups[j-1].NestedGroup.Add(currentGroups[j]);
							else 
								saveGe.NestedGroup.Add(currentGroups[j]);

							saveGe = currentGroups[j];	// retain this GroupEntry
							currentGroups[j] = new GroupEntry(currentGroups[j].Group,currentGroups[j].Sort, rowCurrent);
						}
						savValues = grpValues;
						grpValues = null;
						break;		// break out of the value comparison loop
					}
				}
				rowCurrent++;
			}

			// End of all rows force break on end of rows
			for (i = 0; i < currentGroups.Length; i++)
			{
				currentGroups[i].EndRow = rowCurrent-1;
				if (i == 0)
					wc.Groups.Add(currentGroups[i]);		// top group
				else
					currentGroups[i-1].NestedGroup.Add(currentGroups[i]);
			}
			return;
		}
Example #8
0
		private void RunSetGrouping(Report rpt, WorkClass wc)
		{
			GroupEntry[] currentGroups; 

			// We have some data
			if (_Grouping != null || 
				_Sorting != null)		// fix up the data
			{
				Rows saveData = wc.Data;
				wc.Data = new Rows(rpt, null, _Grouping, _Sorting);
				wc.Data.Data = saveData.Data;
				wc.Data.Sort();
				PrepGroups(rpt, wc);
			}
			// If we haven't formed any groups then form one with all rows
			if (wc.Groups == null)
			{
                wc.Groups = new List<GroupEntry>();
				GroupEntry ge = new GroupEntry(null, null, 0);
				if (wc.Data.Data != null)		// Do we have any data?
					ge.EndRow = wc.Data.Data.Count-1;	// yes
				else
					ge.EndRow = -1;					// no
				wc.Groups.Add(ge);			// top group
				currentGroups = new GroupEntry[1];
			}
			else
				currentGroups = new GroupEntry[1];

			wc.Data.CurrentGroups = currentGroups;

			return;
		}
Example #9
0
        private void RunGroups(IPresent ip, List <GroupEntry> groupEntries, TableWorkClass wc)
        {
            Report     rpt = ip.Report();
            GroupEntry fge = (GroupEntry)(groupEntries[0]);

            if (fge.Group != null)
            {
                ip.GroupingStart(fge.Group);
            }

            foreach (GroupEntry ge in groupEntries)
            {
                // set the group entry value
                int index;
                if (ge.Group != null)                   // groups?
                {
                    ip.GroupingInstanceStart(ge.Group);
                    ge.Group.ResetHideDuplicates(rpt);                  // reset duplicate checking
                    index = ge.Group.GetIndex(rpt);                     // yes
                }
                else                                                    // no; must be main dataset
                {
                    index = 0;
                }
                wc.Data.CurrentGroups[index] = ge;

                if (ge.NestedGroup.Count > 0)
                {
                    RunGroupsSetGroups(rpt, wc, ge.NestedGroup);
                }

                // Handle the group header
                if (ge.Group != null && ge.Group.Parent != null)
                {
                    TableGroup tg = ge.Group.Parent as TableGroup;
                    if (tg != null && tg.Header != null)
                    {
                        // Calculate the number of table rows below this group; header, footer, details count
                        if (ge.NestedGroup.Count > 0)
                        {
                            wc.GroupNestCount = RunGroupsCount(ge.NestedGroup, 0);
                        }
                        else
                        {
                            wc.GroupNestCount = (ge.EndRow - ge.StartRow + 1) * DetailsCount;
                        }
                        tg.Header.Run(ip, wc.Data.Data[ge.StartRow]);
                        wc.GroupNestCount = 0;
                    }
                }
                // Handle the nested groups if any
                if (ge.NestedGroup.Count > 0)
                {
                    RunGroups(ip, ge.NestedGroup, wc);
                }
                // If no nested groups then handle the detail rows for the group
                else if (_Details != null)
                {
                    if (ge.Group != null &&
                        ge.Group.Parent as TableGroup == null)
                    {                           // Group defined on table; means that Detail rows only put out once per group
                        _Details.Run(ip, wc.Data, ge.StartRow, ge.StartRow);
                    }
                    else
                    {
                        _Details.Run(ip, wc.Data, ge.StartRow, ge.EndRow);
                    }
                }

                // Do the group footer
                if (ge.Group != null)
                {
                    if (ge.Group.Parent != null)
                    {
                        TableGroup tg = ge.Group.Parent as TableGroup;                          // detail groups will result in null
                        if (tg != null && tg.Footer != null)
                        {
                            tg.Footer.Run(ip, wc.Data.Data[ge.EndRow]);
                        }
                    }
                    ip.GroupingInstanceEnd(ge.Group);
                }
            }
            if (fge.Group != null)
            {
                ip.GroupingEnd(fge.Group);
            }
        }
Example #10
0
        private void PrepRecursiveGroup(Report rpt, TableWorkClass wc)
        {
            // Prepare for processing recursive group
            Grouping        g          = wc.RecursiveGroup;
            IExpr           parentExpr = g.ParentGroup;
            GroupExpression gexpr      = g.GroupExpressions.Items[0] as GroupExpression;
            IExpr           groupExpr  = gexpr.Expression;
            TypeCode        tc         = groupExpr.GetTypeCode();
            List <Row>      odata      = new List <Row>(wc.Data.Data);          // this is the old data that we'll recreate using the recursive hierarchy
            List <Row>      newrows    = new List <Row>(odata.Count);

            // For now we assume on a single top of tree (and it must sort first as null)
            //   spec is incomplete: should have ability to specify starting value of tree
            // TODO: pull all of the rows that start with null
            newrows.Add(odata[0]);                                              // add the starting row
            odata.RemoveAt(0);                                                  //   remove olddata

            // we need to build the group entry stack
            // Build the initial one
            wc.Groups = new List <GroupEntry>();
            GroupEntry ge = new GroupEntry(null, null, 0);

            ge.EndRow = odata.Count - 1;
            wc.Groups.Add(ge);                                          // top group

            List <GroupEntry> ges = new List <GroupEntry>();

            ges.Add(ge);

            // loop thru the rows and find their children
            //   we place the children right after the parent
            //   this reorders the rows in the form of the hierarchy
            Row r;
            RecursiveCompare rc = new RecursiveCompare(rpt, parentExpr, tc, groupExpr);

            for (int iRow = 0; iRow < newrows.Count; iRow++)            // go thru the temp rows
            {
                r = newrows[iRow];

                r.GroupEntry        = ge = new GroupEntry(g, null, iRow);               // TODO: sort for this group??
                r.GroupEntry.EndRow = iRow;

                // pull out all the rows that match this value
                int iMainRow = odata.BinarySearch(r, rc);
                if (iMainRow < 0)
                {
                    for (int i = 0; i <= r.Level + 1 && i < ges.Count; i++)
                    {
                        ge = ges[i] as GroupEntry;
                        Row rr = newrows[ge.StartRow];                          // start row has the base level of group
                        if (rr.Level < r.Level)
                        {
                            ge.EndRow = iRow;
                        }
                    }
                    continue;
                }

                // look backward for starting row;
                //   in case of duplicates, BinarySearch can land on any of the rows
                object cmpvalue = groupExpr.Evaluate(rpt, r);

                int sRow = iMainRow - 1;
                while (sRow >= 0)
                {
                    object v = parentExpr.Evaluate(rpt, odata[sRow]);
                    if (Filter.ApplyCompare(tc, cmpvalue, v) != 0)
                    {
                        break;
                    }
                    sRow--;
                }
                sRow++;                         // adjust; since we went just prior it
                // look forward for ending row
                int eRow = iMainRow + 1;
                while (eRow < odata.Count)
                {
                    object v = parentExpr.Evaluate(rpt, odata[eRow]);
                    if (Filter.ApplyCompare(tc, cmpvalue, v) != 0)
                    {
                        break;
                    }
                    eRow++;
                }
                // Build a group entry for this
                GroupEntry ge2 = ges[r.Level] as GroupEntry;
                ge2.NestedGroup.Add(ge);
                if (r.Level + 1 >= ges.Count)                   // ensure we have room in the array (based on level)
                {
                    ges.Add(ge);                                // add to the array
                }
                else
                {
                    ges[r.Level + 1] = ge;                                              // put this in the array
                }

                // add all of them in; want the same order for these rows.
                int offset = 1;
                for (int tRow = sRow; tRow < eRow; tRow++)
                {
                    Row tr = odata[tRow];
                    tr.Level = r.Level + 1;
                    newrows.Insert(iRow + offset, tr);
                    offset++;
                }
                // remove from old data
                odata.RemoveRange(sRow, eRow - sRow);
            }

            // update the groupentries for the very last row
            int lastrow = newrows.Count - 1;

            r = newrows[lastrow];
            for (int i = 0; i < r.Level + 1 && i < ges.Count; i++)
            {
                ge        = ges[i] as GroupEntry;
                ge.EndRow = lastrow;
            }

            wc.Data.Data = newrows;                     // we've completely replaced the rows
            return;
        }
Example #11
0
        private void PrepGroups(Report rpt, TableWorkClass wc)
        {
            wc.RecursiveGroup = null;
            if (_TableGroups == null)
            {                   // no tablegroups; check to ensure details is grouped
                if (_Details == null || _Details.Grouping == null)
                {
                    return;                                     // no groups to prepare
                }
            }

            int i = 0;
            // 1) Build array of all GroupExpression objects
            List <GroupExpression> gea = new List <GroupExpression>();
            //    count the number of groups
            int countG = 0;

            if (_TableGroups != null)
            {
                countG = _TableGroups.Items.Count;
            }

            Grouping dg = null;
            Sorting  ds = null;

            if (_Details != null && _Details.Grouping != null)
            {
                dg = _Details.Grouping;
                ds = _Details.Sorting;
                countG++;
            }
            GroupEntry[] currentGroups = new GroupEntry[countG++];
            if (_TableGroups != null)
            {                   // add in the groups for the tablegroup
                foreach (TableGroup tg in _TableGroups.Items)
                {
                    if (tg.Grouping.ParentGroup != null)
                    {
                        wc.RecursiveGroup = tg.Grouping;
                    }
                    tg.Grouping.SetIndex(rpt, i);                               // set the index of this group (so we can find the GroupEntry)
                    currentGroups[i++] = new GroupEntry(tg.Grouping, tg.Sorting, 0);
                    foreach (GroupExpression ge in tg.Grouping.GroupExpressions.Items)
                    {
                        gea.Add(ge);
                    }
                }
            }
            if (dg != null)
            {                   // add in the groups for the details grouping
                if (dg.ParentGroup != null)
                {
                    wc.RecursiveGroup = dg;
                }
                dg.SetIndex(rpt, i);                            // set the index of this group (so we can find the GroupEntry)
                currentGroups[i++] = new GroupEntry(dg, ds, 0);
                foreach (GroupExpression ge in dg.GroupExpressions.Items)
                {
                    gea.Add(ge);
                }
            }

            if (wc.RecursiveGroup != null)
            {
                if (gea.Count != 1)                             // Limitiation of implementation
                {
                    throw new Exception("Error: Recursive groups must be the only group definition.");
                }

                PrepRecursiveGroup(rpt, wc);                    // only one group and it's recursive: optimization
                return;
            }

            // Save the typecodes, and grouping by groupexpression; for later use
            TypeCode[] tcs = new TypeCode[gea.Count];
            Grouping[] grp = new Grouping[gea.Count];
            i = 0;
            foreach (GroupExpression ge in gea)
            {
                grp[i]   = (Grouping)(ge.Parent.Parent);                // remember the group
                tcs[i++] = ge.Expression.GetTypeCode();                 // remember type of expression
            }

            // 2) Loop thru the data, then loop thru the GroupExpression list
            wc.Groups = new List <GroupEntry>();
            object[] savValues  = null;
            object[] grpValues  = null;
            int      rowCurrent = 0;

            foreach (Row row in wc.Data.Data)
            {
                // Get the values for all the group expressions
                if (grpValues == null)
                {
                    grpValues = new object[gea.Count];
                }

                i = 0;
                foreach (GroupExpression ge in gea)
                {
                    if (((Grouping)(ge.Parent.Parent)).ParentGroup == null)
                    {
                        grpValues[i++] = ge.Expression.Evaluate(rpt, row);
                    }
                    else
                    {
                        grpValues[i++] = null;                          // Want all the parentGroup to evaluate equal
                    }
                }

                // For first row we just primed the pump; action starts on next row
                if (rowCurrent == 0)                                    // always start new group on first row
                {
                    rowCurrent++;
                    savValues = grpValues;
                    grpValues = null;
                    continue;
                }

                // compare the values; if change then we have a group break
                for (i = 0; i < savValues.Length; i++)
                {
                    if (Filter.ApplyCompare(tcs[i], savValues[i], grpValues[i]) != 0)
                    {
                        // start a new group; and force a break on every subgroup
                        GroupEntry saveGe = null;
                        for (int j = grp[i].GetIndex(rpt); j < currentGroups.Length; j++)
                        {
                            currentGroups[j].EndRow = rowCurrent - 1;
                            if (j == 0)
                            {
                                wc.Groups.Add(currentGroups[j]);                                                // top group
                            }
                            else if (saveGe == null)
                            {
                                currentGroups[j - 1].NestedGroup.Add(currentGroups[j]);
                            }
                            else
                            {
                                saveGe.NestedGroup.Add(currentGroups[j]);
                            }

                            saveGe           = currentGroups[j];                        // retain this GroupEntry
                            currentGroups[j] = new GroupEntry(currentGroups[j].Group, currentGroups[j].Sort, rowCurrent);
                        }
                        savValues = grpValues;
                        grpValues = null;
                        break;                                  // break out of the value comparison loop
                    }
                }
                rowCurrent++;
            }

            // End of all rows force break on end of rows
            for (i = 0; i < currentGroups.Length; i++)
            {
                currentGroups[i].EndRow = rowCurrent - 1;
                if (i == 0)
                {
                    wc.Groups.Add(currentGroups[i]);                                    // top group
                }
                else
                {
                    currentGroups[i - 1].NestedGroup.Add(currentGroups[i]);
                }
            }

            return;
        }
Example #12
0
        void RunPrep(Report rpt, Row row, TableWorkClass wc)
        {
            GroupEntry[] currentGroups;

            // We have some data
            if (_TableGroups != null ||
                (_Details != null &&
                 (_Details.Sorting != null ||
                  _Details.Grouping != null)))                          // fix up the data
            {
                List <Row> saveData = wc.Data.Data;
                Grouping   gr;
                Sorting    srt;
                if (_Details == null)
                {
                    gr = null;  srt = null;
                }
                else
                {
                    gr  = _Details.Grouping;
                    srt = _Details.Sorting;
                }

                wc.Data      = new Rows(rpt, _TableGroups, gr, srt);
                wc.Data.Data = saveData;
                wc.Data.Sort();
                PrepGroups(rpt, wc);
            }

            // If we haven't formed any groups then form one with all rows
            if (wc.Groups == null)
            {
                wc.Groups = new List <GroupEntry>();
                GroupEntry ge = new GroupEntry(null, null, 0);
                if (wc.Data.Data != null)                               // Do we have any data?
                {
                    ge.EndRow = wc.Data.Data.Count - 1;                 // yes
                }
                else
                {
                    ge.EndRow = -1;                                     // no
                }
                wc.Groups.Add(ge);                                      // top group
                currentGroups = new GroupEntry[1];
            }
            else if (_TableGroups != null)
            {
                int count = _TableGroups.Items.Count;
                if (_Details != null && _Details.Grouping != null)
                {
                    count++;
                }

                currentGroups = new GroupEntry[count];
            }
            else
            {
                currentGroups = new GroupEntry[1];
            }

            wc.Data.CurrentGroups = currentGroups;

            SortGroups(rpt, wc.Groups, wc);
        }
Example #13
0
        // return an IEnumerable that represents the scope of the data
        protected RowEnumerable GetDataScope(Report rpt, Row row, out bool bSave)
        {
            bSave = true;
            RowEnumerable re = null;

            if (this._Scope != null)
            {
                Type t = this._Scope.GetType();

                //150208AJM GJL Trying - And Succeeding!!! to get data from chart
                if (t == typeof(Chart))
                {
                    Chart c = (Chart)this._Scope;
                    this._Scope = c.ChartMatrix;
                    t           = this._Scope.GetType();
                }

                if (t == typeof(Grouping))
                {
                    bSave = false;
                    Grouping g = (Grouping)(this._Scope);
                    if (g.InMatrix)
                    {
                        Rows rows = g.GetRows(rpt);
                        if (rows == null)
                        {
                            return(null);
                        }
                        re = new RowEnumerable(0, rows.Data.Count - 1, rows.Data, _LevelCheck);
                    }
                    else
                    {
                        if (row == null || row.R.CurrentGroups == null)                             // currentGroups can be null when reference Textbox in header/footer that has a scoped aggr function reference (TODO: this is a problem!)
                        {
                            return(null);
                        }
                        GroupEntry ge = row.R.CurrentGroups[g.GetIndex(rpt)];
                        re = new RowEnumerable(ge.StartRow, ge.EndRow, row.R.Data, _LevelCheck);
                    }
                }
                else if (t == typeof(Matrix))
                {
                    bSave = false;
                    Matrix m     = (Matrix)(this._Scope);
                    Rows   mData = m.GetMyData(rpt);
                    re = new RowEnumerable(0, mData.Data.Count - 1, mData.Data, false);
                }
                else if (t == typeof(string))
                {                       // happens on page header/footer scope
                    if (row != null)
                    {
                        re = new RowEnumerable(0, row.R.Data.Count - 1, row.R.Data, false);
                    }
                    bSave = false;
                }
                else if (row != null)
                {
                    re = new RowEnumerable(0, row.R.Data.Count - 1, row.R.Data, false);
                }
                else
                {
                    DataSetDefn ds = this._Scope as DataSetDefn;
                    if (ds != null && ds.Query != null)
                    {
                        Rows rows = ds.Query.GetMyData(rpt);
                        if (rows != null)
                        {
                            re = new RowEnumerable(0, rows.Data.Count - 1, rows.Data, false);
                        }
                    }
                }
            }
            else if (row != null)
            {
                re = new RowEnumerable(0, row.R.Data.Count - 1, row.R.Data, false);
            }

            return(re);
        }