bool _InMatrix;                           // true if grouping is in a matrix

        internal Grouping(ReportDefn r, ReportLink p, XmlNode xNode) : base(r, p)
        {
            _Name               = null;
            _Label              = null;
            _GroupExpressions   = null;
            _PageBreakAtStart   = false;
            _PageBreakAtEnd     = false;
            _Custom             = null;
            _Filters            = null;
            _ParentGroup        = null;
            _DataElementName    = null;
            _DataCollectionName = null;
            _DataElementOutput  = DataElementOutputEnum.Output;
            _HideDuplicates     = null;
            // Run thru the attributes
            foreach (XmlAttribute xAttr in xNode.Attributes)
            {
                switch (xAttr.Name)
                {
                case "Name":
                    _Name = new Name(xAttr.Value);
                    break;
                }
            }
            // Loop thru all the child nodes
            foreach (XmlNode xNodeLoop in xNode.ChildNodes)
            {
                if (xNodeLoop.NodeType != XmlNodeType.Element)
                {
                    continue;
                }
                switch (xNodeLoop.Name)
                {
                case "Label":
                    _Label = new Expression(r, this, xNodeLoop, ExpressionType.String);
                    break;

                case "GroupExpressions":
                    _GroupExpressions = new GroupExpressions(r, this, xNodeLoop);
                    break;

                case "PageBreakAtStart":
                    _PageBreakAtStart = XmlUtil.Boolean(xNodeLoop.InnerText, OwnerReport.rl);
                    break;

                case "PageBreakAtEnd":
                    _PageBreakAtEnd = XmlUtil.Boolean(xNodeLoop.InnerText, OwnerReport.rl);
                    break;

                case "Custom":
                    _Custom = new Custom(r, this, xNodeLoop);
                    break;

                case "Filters":
                    _Filters = new Filters(r, this, xNodeLoop);
                    break;

                case "Parent":
                    _ParentGroup = new Expression(r, this, xNodeLoop, ExpressionType.Variant);
                    break;

                case "DataElementName":
                    _DataElementName = xNodeLoop.InnerText;
                    break;

                case "DataCollectionName":
                    _DataCollectionName = xNodeLoop.InnerText;
                    break;

                case "DataElementOutput":
                    _DataElementOutput = Engine.DataElementOutput.GetStyle(xNodeLoop.InnerText, OwnerReport.rl);
                    break;

                default:
                    // don't know this element - log it
                    OwnerReport.rl.LogError(4, "Unknown Grouping element '" + xNodeLoop.Name + "' ignored.");
                    break;
                }
            }
            if (this.Name != null)
            {
                try
                {
                    OwnerReport.LUAggrScope.Add(this.Name.Nm, this); // add to referenceable Grouping's
                }
                catch                                                // wish duplicate had its own exception
                {
                    OwnerReport.rl.LogError(8, "Duplicate Grouping name '" + this.Name.Nm + "'.");
                }
            }
            if (_GroupExpressions == null)
            {
                OwnerReport.rl.LogError(8, "Group Expressions are required within group '" + (this.Name == null? "unnamed": this.Name.Nm) + "'.");
            }
        }
        Expression _ParentGroup; //(Variant)

        #endregion Fields

        #region Constructors

        internal Grouping(ReportDefn r, ReportLink p, XmlNode xNode)
            : base(r, p)
        {
            _Name=null;
            _Label=null;
            _GroupExpressions=null;
            _PageBreakAtStart=false;
            _PageBreakAtEnd=false;
            _Custom=null;
            _Filters=null;
            _ParentGroup=null;
            _DataElementName=null;
            _DataCollectionName=null;
            _DataElementOutput=DataElementOutputEnum.Output;
            _HideDuplicates=null;
            // Run thru the attributes
            foreach(XmlAttribute xAttr in xNode.Attributes)
            {
                switch (xAttr.Name)
                {
                    case "Name":
                        _Name = new Name(xAttr.Value);
                        break;
                }
            }
            // Loop thru all the child nodes
            foreach(XmlNode xNodeLoop in xNode.ChildNodes)
            {
                if (xNodeLoop.NodeType != XmlNodeType.Element)
                    continue;
                switch (xNodeLoop.Name)
                {
                    case "Label":
                        _Label = new Expression(r, this, xNodeLoop, ExpressionType.String);
                        break;
                    case "GroupExpressions":
                        _GroupExpressions = new GroupExpressions(r, this, xNodeLoop);
                        break;
                    case "PageBreakAtStart":
                        _PageBreakAtStart = XmlUtil.Boolean(xNodeLoop.InnerText, OwnerReport.rl);
                        break;
                    case "PageBreakAtEnd":
                        _PageBreakAtEnd = XmlUtil.Boolean(xNodeLoop.InnerText, OwnerReport.rl);
                        break;
                    case "Custom":
                        _Custom = new Custom(r, this, xNodeLoop);
                        break;
                    case "Filters":
                        _Filters = new Filters(r, this, xNodeLoop);
                        break;
                    case "Parent":
                        _ParentGroup = new Expression(r, this, xNodeLoop, ExpressionType.Variant);
                        break;
                    case "DataElementName":
                        _DataElementName = xNodeLoop.InnerText;
                        break;
                    case "DataCollectionName":
                        _DataCollectionName = xNodeLoop.InnerText;
                        break;
                    case "DataElementOutput":
                        _DataElementOutput = Engine.DataElementOutput.GetStyle(xNodeLoop.InnerText, OwnerReport.rl);
                        break;
                    default:
                        // don't know this element - log it
                        OwnerReport.rl.LogError(4, "Unknown Grouping element '" + xNodeLoop.Name + "' ignored.");
                        break;
                }
            }
            if (this.Name != null)
            {
                try
                {
                    OwnerReport.LUAggrScope.Add(this.Name.Nm, this);		// add to referenceable Grouping's
                }
                catch	// wish duplicate had its own exception
                {
                    OwnerReport.rl.LogError(8, "Duplicate Grouping name '" + this.Name.Nm + "'.");
                }
            }
            if (_GroupExpressions == null)
                OwnerReport.rl.LogError(8, "Group Expressions are required within group '" + (this.Name==null? "unnamed": this.Name.Nm) + "'.");
        }