Sorting _Sorting; // The expressions to sort the data by #endregion Fields #region Constructors internal DynamicCategories(ReportDefn r, ReportLink p, XmlNode xNode) : base(r, p) { _Grouping=null; _Sorting=null; _Label=null; // Loop thru all the child nodes foreach(XmlNode xNodeLoop in xNode.ChildNodes) { if (xNodeLoop.NodeType != XmlNodeType.Element) continue; switch (xNodeLoop.Name) { case "Grouping": _Grouping = new Grouping(r, this, xNodeLoop); break; case "Sorting": _Sorting = new Sorting(r, this, xNodeLoop); break; case "Label": _Label = new Expression(r, this, xNodeLoop, ExpressionType.Variant); break; default: break; } } if (_Grouping == null) OwnerReport.rl.LogError(8, "DynamicCategories requires the Grouping element."); }
int _StartRow; // Starting row of the group (inclusive) #endregion Fields #region Constructors internal GroupEntry(Grouping g, Sorting s, int start) { _Group = g; _Sort = s; _StartRow = start; _EndRow = -1; _NestedGroup = new List<GroupEntry>(); // Check to see if grouping and sorting are the same if (g == null || s == null) return; // nothing to check if either is null if (s.Items.Count != g.GroupExpressions.Items.Count) return; for (int i = 0; i < s.Items.Count; i++) { SortBy sb = s.Items[i] as SortBy; if (sb.Direction == SortDirectionEnum.Descending) return; // TODO we could optimize this FunctionField ff = sb.SortExpression.Expr as FunctionField; if (ff == null || ff.GetTypeCode() != TypeCode.String) return; GroupExpression ge = g.GroupExpressions.Items[i] as GroupExpression; FunctionField ff2 = ge.Expression.Expr as FunctionField; if (ff2 == null || ff.Fld != ff2.Fld) return; } _Sort = null; // we won't need to sort since the groupby will handle it correctly }
Visibility _Visibility; // Indicates if all of the dynamic rows for this grouping #endregion Fields #region Constructors // should be hidden and replaced with a subtotal row for // this grouping scope internal DynamicRows(ReportDefn r, ReportLink p, XmlNode xNode) : base(r, p) { _Grouping=null; _Sorting=null; _Subtotal=null; _ReportItems=null; _Visibility=null; // Run thru the attributes // foreach(XmlAttribute xAttr in xNode.Attributes) // { // } // Loop thru all the child nodes foreach(XmlNode xNodeLoop in xNode.ChildNodes) { if (xNodeLoop.NodeType != XmlNodeType.Element) continue; switch (xNodeLoop.Name) { case "Grouping": _Grouping = new Grouping(r, this, xNodeLoop); break; case "Sorting": _Sorting = new Sorting(r, this, xNodeLoop); break; case "Subtotal": _Subtotal = new Subtotal(r, this, xNodeLoop); break; case "ReportItems": _ReportItems = new ReportItems(r, this, xNodeLoop); break; case "Visibility": _Visibility = new Visibility(r, this, xNodeLoop); break; default: // don't know this element - log it OwnerReport.rl.LogError(4, "Unknown DynamicRow element '" + xNodeLoop.Name + "' ignored."); break; } } if (_Grouping == null) OwnerReport.rl.LogError(8, "DynamicRows requires the Grouping element."); if (_ReportItems == null || _ReportItems.Items.Count != 1) OwnerReport.rl.LogError(8, "DynamicRows requires the ReportItems element defined with exactly one report item."); }
Visibility _Visibility; // Indicates if the group (and all groups embedded #endregion Fields #region Constructors internal TableGroup(ReportDefn r, ReportLink p, XmlNode xNode) : base(r, p) { _Grouping=null; _Sorting=null; _Header=null; _Footer=null; _Visibility=null; _ToggleTextbox=null; // Loop thru all the child nodes foreach(XmlNode xNodeLoop in xNode.ChildNodes) { if (xNodeLoop.NodeType != XmlNodeType.Element) continue; switch (xNodeLoop.Name) { case "Grouping": _Grouping = new Grouping(r, this, xNodeLoop); break; case "Sorting": _Sorting = new Sorting(r, this, xNodeLoop); break; case "Header": _Header = new Header(r, this, xNodeLoop); break; case "Footer": _Footer = new Footer(r, this, xNodeLoop); break; case "Visibility": _Visibility = new Visibility(r, this, xNodeLoop); break; default: // don't know this element - log it OwnerReport.rl.LogError(4, "Unknown TableGroup element '" + xNodeLoop.Name + "' ignored."); break; } } if (_Grouping == null) OwnerReport.rl.LogError(8, "TableGroup requires the Grouping element."); }
Sorting _Sorting; // The expressions to sort the repeated list regions by #endregion Fields #region Constructors internal List(ReportDefn r, ReportLink p, XmlNode xNode) : base(r,p,xNode) { _Grouping=null; _Sorting=null; _ReportItems=null; _DataInstanceName="Item"; _DataInstanceElementOutput=DataInstanceElementOutputEnum.Output; // Loop thru all the child nodes foreach(XmlNode xNodeLoop in xNode.ChildNodes) { if (xNodeLoop.NodeType != XmlNodeType.Element) continue; switch (xNodeLoop.Name) { case "Grouping": _Grouping = new Grouping(r, this, xNodeLoop); break; case "Sorting": _Sorting = new Sorting(r, this, xNodeLoop); break; case "ReportItems": _ReportItems = new ReportItems(r, this, xNodeLoop); break; case "DataInstanceName": _DataInstanceName = xNodeLoop.InnerText; break; case "DataInstanceElementOutput": _DataInstanceElementOutput = Engine.DataInstanceElementOutput.GetStyle(xNodeLoop.InnerText, OwnerReport.rl); break; default: if (DataRegionElement(xNodeLoop)) // try at DataRegion level break; // don't know this element - log it OwnerReport.rl.LogError(4, "Unknown List element '" + xNodeLoop.Name + "' ignored."); break; } } DataRegionFinish(); // Tidy up the DataRegion }
Visibility _Visibility; // Indicates if the details should be hidden #endregion Fields #region Constructors internal Details(ReportDefn r, ReportLink p, XmlNode xNode) : base(r, p) { _TableRows=null; _Grouping=null; _Sorting=null; _Visibility=null; _ToggleTextbox = null; // Loop thru all the child nodes foreach(XmlNode xNodeLoop in xNode.ChildNodes) { if (xNodeLoop.NodeType != XmlNodeType.Element) continue; switch (xNodeLoop.Name) { case "TableRows": _TableRows = new TableRows(r, this, xNodeLoop); break; case "Grouping": _Grouping = new Grouping(r, this, xNodeLoop); break; case "Sorting": _Sorting = new Sorting(r, this, xNodeLoop); break; case "Visibility": _Visibility = new Visibility(r, this, xNodeLoop); break; default: // don't know this element - log it OwnerReport.rl.LogError(4, "Unknown Details element " + xNodeLoop.Name + " ignored."); break; } } if (_TableRows == null) OwnerReport.rl.LogError(8, "Details requires the TableRows element."); }
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; }