override internal void RunPage(Pages pgs, Row row) { Report rpt = pgs.Report; if (IsHidden(pgs.Report, row)) { return; } _ChartMatrix.RunReset(rpt); Rows _Data = GetFilteredData(rpt, row); SetMyData(rpt, _Data); SetPagePositionBegin(pgs); if (!AnyRowsPage(pgs, _Data)) // if no rows return { return; // nothing left to do } // Build the Chart bitmap, along with data regions Page p = pgs.CurrentPage; ChartBase cb = null; try { cb = RunChartBuild(rpt, row); // Build the chart if (!_isHYNEsWonderfulVector.EvaluateBoolean(rpt, row)) //AJM GJL 14082008 'Classic' Rendering { System.DrawingCore.Image im = cb.Image(rpt); // Grab the image int height = im.Height; // save height and width int width = im.Width; MemoryStream ostrm = new MemoryStream(); /* The following is a new image saving logic which will allow for higher * quality images using JPEG with 100% quality * 06122007AJM */ System.DrawingCore.Imaging.ImageCodecInfo[] info; info = ImageCodecInfo.GetImageEncoders(); EncoderParameters encoderParameters; encoderParameters = new EncoderParameters(1); // 20022008 AJM GJL - Centralised class with global encoder settings encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, ImageQualityManager.ChartImageQuality); System.DrawingCore.Imaging.ImageCodecInfo codec = null; for (int i = 0; i < info.Length; i++) { if (info[i].FormatDescription == "JPEG") { codec = info[i]; break; } } im.Save(ostrm, codec, encoderParameters); // 06122007AJM The follow has been replaced with the code above //im.Save(ostrm, info); // generate a jpeg TODO: get png to work with pdf byte[] ba = ostrm.ToArray(); ostrm.Close(); PageImage pi = new PageImage(IMAGEFORMAT, ba, width, height); // Create an image RunPageRegionBegin(pgs); SetPagePositionAndStyle(rpt, pi, row); pi.SI.BackgroundImage = null; // chart already has the background image if (pgs.CurrentPage.YOffset + pi.Y + pi.H >= pgs.BottomOfPage && !pgs.CurrentPage.IsEmpty()) { // force page break if it doesn't fit on the page pgs.NextOrNew(); pgs.CurrentPage.YOffset = OwnerReport.TopOfPage; if (this.YParents != null) { pi.Y = 0; } } p = pgs.CurrentPage; p.AddObject(pi); // Put image onto the current page RunPageRegionEnd(pgs); if (!this.PageBreakAtEnd && !IsTableOrMatrixCell(rpt)) { float newY = pi.Y + pi.H; p.YOffset += newY; // bump the y location } SetPagePositionEnd(pgs, pi.Y + pi.H); } else //Ultimate Rendering - Vector //AJM GJL 14082008 { System.DrawingCore.Imaging.Metafile im = cb.Image(rpt); // Grab the image //im could still be saved to a bitmap at this point //if we were to offer a choice of raster or vector, it would probably //be easiest to draw the chart to the EMF and then save as bitmap if needed int height = im.Height; // save height and width int width = im.Width; byte[] ba = cb._aStream.ToArray(); cb._aStream.Close(); PageImage pi = new PageImage(ImageFormat.Wmf, ba, width, height); RunPageRegionBegin(pgs); SetPagePositionAndStyle(rpt, pi, row); pi.SI.BackgroundImage = null; // chart already has the background image if (pgs.CurrentPage.YOffset + pi.Y + pi.H >= pgs.BottomOfPage && !pgs.CurrentPage.IsEmpty()) { // force page break if it doesn't fit on the page pgs.NextOrNew(); pgs.CurrentPage.YOffset = OwnerReport.TopOfPage; if (this.YParents != null) { pi.Y = 0; } } p = pgs.CurrentPage; //GJL 25072008 - Charts now draw in EMFplus format and not in bitmap. Still using the "PageImage" for the positioning //paging etc, but we don't add it to the page. // ****************************************************************************************************************** // New EMF Processing... we want to add the EMF Components to the page and not the actual EMF... EMF emf = new EMF(pi.X, pi.Y, width, height); emf.ProcessEMF(ba); //Process takes the bytearray of EMFplus data and breaks it down into lines,ellipses,text,rectangles //etc... There are still a lot of GDI+ functions I haven't got to (and some I have no intention of getting to!). foreach (PageItem emfItem in emf.PageItems) { p.AddObject(emfItem); } // ****************************************************************************************************************** //p.AddObject(pi); RunPageRegionEnd(pgs); pi.Y += p.YOffset; if (!this.PageBreakAtEnd && !IsTableOrMatrixCell(rpt)) { float newY = pi.Y + pi.H; p.YOffset += newY; // bump the y location } SetPagePositionEnd(pgs, pi.Y + pi.H); //our emf size seems to be bigger than the jpeg... } } catch (Exception ex) { rpt.rl.LogError(8, string.Format("Exception in Chart handling.\n{0}\n{1}", ex.Message, ex.StackTrace)); } finally { if (cb != null) { cb.Dispose(); } } return; }
void DrawPlotAreaDoughnut(Report rpt, Graphics g) { // Draw Plot area data int widthPie = Layout.PlotArea.Width; int maxHeight = Layout.PlotArea.Height; int maxPieSize = Math.Min(widthPie, maxHeight); int doughWidth = maxPieSize / 4 / CategoryCount; if (doughWidth < 2) { doughWidth = 2; // enforce minimum width } float startAngle; float endAngle; int pieLocX; int pieLocY; int pieSize; // Go and draw the pies int left = Layout.PlotArea.Left + (maxPieSize == widthPie? 0: (widthPie - maxPieSize) / 2); int top = Layout.PlotArea.Top + (maxPieSize == maxHeight? 0: (maxHeight - maxPieSize) / 2); for (int iRow = 1; iRow <= CategoryCount; iRow++) { pieLocX = left + ((iRow - 1) * doughWidth); pieLocY = top + ((iRow - 1) * doughWidth); double total = 0; // sum up for this category for (int iCol = 1; iCol <= SeriesCount; iCol++) { total += this.GetDataValue(rpt, iRow, iCol); } // Pie size decreases as we go in startAngle = 0.0f; pieSize = maxPieSize - ((iRow - 1) * doughWidth * 2); for (int iCol = 1; iCol <= SeriesCount; iCol++) { double v = this.GetDataValue(rpt, iRow, iCol); endAngle = (float)(startAngle + v / total * 360); DrawPie(g, rpt, GetSeriesBrush(rpt, iRow, iCol), new System.DrawingCore.Rectangle(pieLocX, pieLocY, pieSize, pieSize), iRow, iCol, startAngle, endAngle); startAngle = endAngle; } } // Now draw the center hole with the plot area style if (ChartDefn.PlotArea == null || ChartDefn.PlotArea.Style == null) { return; } pieLocX = left + (CategoryCount * doughWidth); pieLocY = top + (CategoryCount * doughWidth); pieSize = maxPieSize - (CategoryCount * doughWidth * 2); System.DrawingCore.Rectangle rect = new System.DrawingCore.Rectangle(pieLocX, pieLocY, pieSize, pieSize); Style s = ChartDefn.PlotArea.Style; Rows cData = ChartDefn.ChartMatrix.GetMyData(rpt); Row r = cData.Data[0]; s.DrawBackgroundCircle(rpt, g, r, rect); }
internal Rows GetFilteredData(Report rpt, Row row) { try { Rows data; if (this._Filters == null) { if (this._ParentDataRegion == null) { data = DataSetDefn.Query.GetMyData(rpt); return(data == null? null: new Rows(rpt, data)); // We need to copy in case DataSet is shared by multiple DataRegions } else { return(GetNestedData(rpt, row)); } } if (this._ParentDataRegion == null) { data = DataSetDefn.Query.GetMyData(rpt); if (data != null) { data = new Rows(rpt, data); } } else { data = GetNestedData(rpt, row); } if (data == null) { return(null); } List <Row> ar = new List <Row>(); foreach (Row r in data.Data) { if (_Filters.Apply(rpt, r)) { ar.Add(r); } } ar.TrimExcess(); data.Data = ar; _Filters.ApplyFinalFilters(rpt, data, true); // Adjust the rowcount int rCount = 0; foreach (Row r in ar) { r.RowNumber = rCount++; } return(data); } catch (Exception e) { this.OwnerReport.rl.LogError(8, e.Message); return(null); } }
int _ColSpan; // # of columns spanned internal MatrixCellEntry(Rows d, ReportItem ri) { _Data = d; _DisplayItem = ri; _ColSpan = 1; }
// 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 (t == typeof(DataSetDefn)) { 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); } 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); }
private void ApplyTopBottomFilter(Report rpt, Rows data) { if (data.Data.Count <= 0) // No data; nothing to do { return; } // Get the filter value and validate it FilterValue fv = this._FilterValues.Items[0]; double val = fv.Expression.EvaluateDouble(rpt, data.Data[0]); if (val <= 0) // if less than equal 0; then request results in no data { data.Data.Clear(); return; } // Calculate the row number of the affected item and do additional validation int ival; if (_FilterOperator == FilterOperatorEnum.TopN || _FilterOperator == FilterOperatorEnum.BottomN) { ival = (int)val; if (ival != val) { throw new Exception(string.Format("Filter operators TopN and BottomN require an integer value got {0}.", val)); } if (ival >= data.Data.Count) // includes all the data? { return; } ival--; // make zero based } else { if (val >= 100) // greater than 100% means all the data { return; } ival = (int)(data.Data.Count * (val / 100)); if (ival <= 0) // if less than equal 0; then request results in no data { data.Data.Clear(); return; } if (ival >= data.Data.Count) // make sure rounding hasn't forced us past 100% { return; } ival--; // make zero based } // Sort the data by the FilterExpression List <RowsSortExpression> sl = new List <RowsSortExpression>(); sl.Add(new RowsSortExpression(this._FilterExpression)); data.SortBy = sl; // update the sort by data.Sort(); // sort the data // reverse the order of the data for top so that data is in the beginning if (_FilterOperator == FilterOperatorEnum.TopN || _FilterOperator == FilterOperatorEnum.TopPercent) { data.Data.Reverse(); } List <Row> ar = data.Data; TypeCode tc = _FilterExpression.GetTypeCode(); object o = this._FilterExpression.Evaluate(rpt, data.Data[ival]); // adjust the ival based on duplicate values ival++; while (ival < ar.Count) { object n = this._FilterExpression.Evaluate(rpt, data.Data[ival]); if (ApplyCompare(tc, o, n) != 0) { break; } ival++; } if (ival < ar.Count) // if less than we need to remove the rest of the rows { ar.RemoveRange(ival, ar.Count - ival); } return; }
object[] _Data; // Row of data internal Row(Rows r, Row rd) // Constructor that uses existing Row data { _R = r; _Data = rd.Data; _Level = rd.Level; }
internal Row(Rows r, int columnCount) { _R = r; _Data = new object[columnCount]; _Level = 0; }
internal void SetData(Report rpt, XmlDocument xmlDoc, Fields flds, Filters f) { if (xmlDoc == null) // Does user want to remove user data? { SetMyUserData(rpt, null); return; } Rows rows = new Rows(rpt,null,null,null); // no sorting and grouping at base data XmlNode xNode; xNode = xmlDoc.LastChild; if (xNode == null || !(xNode.Name == "Rows" || xNode.Name == "fyi:Rows")) { throw new Exception(Strings.Query_Error_XMLMustContainTopLevelRows); } List<Row> ar = new List<Row>(); rows.Data = ar; int rowCount=0; int fieldCount = flds.Items.Count; foreach(XmlNode xNodeRow in xNode.ChildNodes) { if (xNodeRow.NodeType != XmlNodeType.Element) continue; if (xNodeRow.Name != "Row") continue; Row or = new Row(rows, fieldCount); foreach (XmlNode xNodeColumn in xNodeRow.ChildNodes) { Field fld = (Field) (flds.Items[xNodeColumn.Name]); // Find the column if (fld == null) continue; // Extraneous data is ignored if (xNodeColumn.InnerText == null || xNodeColumn.InnerText.Length == 0) or.Data[fld.ColumnNumber] = null; else if (fld.Type == TypeCode.String) or.Data[fld.ColumnNumber] = xNodeColumn.InnerText; else { try { or.Data[fld.ColumnNumber] = Convert.ChangeType(xNodeColumn.InnerText, fld.Type, NumberFormatInfo.InvariantInfo); } catch // all conversion errors result in a null value { or.Data[fld.ColumnNumber] = null; } } } // Apply the filters if (f == null || f.Apply(rpt, or)) { or.RowNumber = rowCount; // rowCount++; ar.Add(or); } } ar.TrimExcess(); // free up any extraneous space; can be sizeable for large # rows if (f != null) f.ApplyFinalFilters(rpt, rows, false); SetMyUserData(rpt, rows); }
// Obtain the data from the XML internal bool GetData(Report rpt, string xmlData, Fields flds, Filters f) { Rows uData = this.GetMyUserData(rpt); if (uData != null) { this.SetMyData(rpt, uData); return uData.Data == null || uData.Data.Count == 0? false: true; } int fieldCount = flds.Items.Count; XmlDocument doc = new XmlDocument(); doc.PreserveWhitespace = false; doc.LoadXml(xmlData); XmlNode xNode; xNode = doc.LastChild; if (xNode == null || !(xNode.Name == "Rows" || xNode.Name == "fyi:Rows")) { throw new Exception(Strings.Query_Error_XMLMustContainTopLevelRows); } Rows _Data = new Rows(rpt, null,null,null); List<Row> ar = new List<Row>(); _Data.Data = ar; int rowCount=0; foreach(XmlNode xNodeRow in xNode.ChildNodes) { if (xNodeRow.NodeType != XmlNodeType.Element) { continue; } if (xNodeRow.Name != "Row") { continue; } Row or = new Row(_Data, fieldCount); foreach (XmlNode xNodeColumn in xNodeRow.ChildNodes) { Field fld = (Field) (flds.Items[xNodeColumn.Name]); // Find the column if (fld == null) { continue; // Extraneous data is ignored } TypeCode tc = fld.qColumn != null? fld.qColumn.colType: fld.Type; if (xNodeColumn.InnerText == null || xNodeColumn.InnerText.Length == 0) { or.Data[fld.ColumnNumber] = null; } else if (tc == TypeCode.String) { or.Data[fld.ColumnNumber] = xNodeColumn.InnerText; } else if (tc == TypeCode.DateTime) { try { or.Data[fld.ColumnNumber] = Convert.ToDateTime(xNodeColumn.InnerText, System.Globalization.DateTimeFormatInfo.InvariantInfo); } catch // all conversion errors result in a null value { or.Data[fld.ColumnNumber] = null; } } else { try { or.Data[fld.ColumnNumber] = Convert.ChangeType(xNodeColumn.InnerText, tc, NumberFormatInfo.InvariantInfo); } catch // all conversion errors result in a null value { or.Data[fld.ColumnNumber] = null; } } } // Apply the filters if (f == null || f.Apply(rpt, or)) { or.RowNumber = rowCount; // rowCount++; ar.Add(or); } } ar.TrimExcess(); // free up any extraneous space; can be sizeable for large # rows if (f != null) { f.ApplyFinalFilters(rpt, _Data, false); } SetMyData(rpt, _Data); return _Data == null || _Data.Data == null || _Data.Data.Count == 0 ? false : true; }
internal bool GetData(Report rpt, Fields flds, Filters f) { Rows uData = this.GetMyUserData(rpt); if (uData != null) { this.SetMyData(rpt, uData); return uData.Data == null || uData.Data.Count == 0 ? false : true; } // Treat this as a SQL statement DataSourceDefn ds = _DataSourceDefn; if (ds == null || _CommandText == null) { this.SetMyData(rpt, null); return false; } IDbConnection cnSQL = ds.SqlConnect(rpt); if (cnSQL == null) { this.SetMyData(rpt, null); return false; } Rows _Data = new Rows(rpt, null,null,null); // no sorting and grouping at base data String sql = _CommandText.EvaluateString(rpt, null); IDbCommand cmSQL=null; IDataReader dr=null; try { cmSQL = cnSQL.CreateCommand(); cmSQL.CommandText = AddParametersAsLiterals(rpt, cnSQL, sql, true); if (this._QueryCommandType == QueryCommandTypeEnum.StoredProcedure) cmSQL.CommandType = CommandType.StoredProcedure; if (this._Timeout > 0) cmSQL.CommandTimeout = this._Timeout; AddParameters(rpt, cnSQL, cmSQL, true); dr = cmSQL.ExecuteReader(CommandBehavior.SingleResult); List<Row> ar = new List<Row>(); _Data.Data = ar; int rowCount=0; int maxRows = _RowLimit > 0? _RowLimit: int.MaxValue; int fieldCount = flds.Items.Count; // Determine the query column number for each field int[] qcn = new int[flds.Items.Count]; foreach (Field fld in flds) { qcn[fld.ColumnNumber] = -1; if (fld.Value != null) continue; try { qcn[fld.ColumnNumber] = dr.GetOrdinal(fld.DataField); } catch { qcn[fld.ColumnNumber] = -1; } } while (dr.Read()) { Row or = new Row(_Data, fieldCount); foreach (Field fld in flds) { if (qcn[fld.ColumnNumber] != -1) { or.Data[fld.ColumnNumber] = dr.GetValue(qcn[fld.ColumnNumber]); } } // Apply the filters if (f == null || f.Apply(rpt, or)) { or.RowNumber = rowCount; // rowCount++; ar.Add(or); } if (--maxRows <= 0) // don't retrieve more than max break; } ar.TrimExcess(); // free up any extraneous space; can be sizeable for large # rows if (f != null) f.ApplyFinalFilters(rpt, _Data, false); //#if DEBUG // rpt.rl.LogError(4, "Rows Read:" + ar.Count.ToString() + " SQL:" + sql ); //#endif } catch (Exception e) { // Issue #35 - Kept the logging rpt.rl.LogError(8, "SQL Exception" + e.Message + "\r\n" + e.StackTrace); throw; } finally { if (cmSQL != null) { cmSQL.Dispose(); if (dr != null) dr.Close(); } } this.SetMyData(rpt, _Data); return _Data == null || _Data.Data == null || _Data.Data.Count == 0 ? false : true; }
override internal void RunPage(Pages pgs, Row row) { Report rpt = pgs.Report; if (IsHidden(pgs.Report, row)) { return; } _ChartMatrix.RunReset(rpt); Rows _Data = GetFilteredData(rpt, row); SetMyData(rpt, _Data); SetPagePositionBegin(pgs); if (!AnyRowsPage(pgs, _Data)) // if no rows return { return; // nothing left to do } // Build the Chart bitmap, along with data regions Page p = pgs.CurrentPage; ChartBase cb = null; try { cb = RunChartBuild(rpt, row); // Build the chart System.Drawing.Image im = cb.Image(rpt); // Grab the image int height = im.Height; // save height and width int width = im.Width; MemoryStream ostrm = new MemoryStream(); im.Save(ostrm, IMAGEFORMAT); // generate a jpeg TODO: get png to work with pdf byte[] ba = ostrm.ToArray(); ostrm.Close(); PageImage pi = new PageImage(IMAGEFORMAT, ba, width, height); // Create an image RunPageRegionBegin(pgs); SetPagePositionAndStyle(rpt, pi, row); pi.SI.BackgroundImage = null; // chart already has the background image if (pgs.CurrentPage.YOffset + pi.Y + pi.H >= pgs.BottomOfPage && !pgs.CurrentPage.IsEmpty()) { // force page break if it doesn't fit on the page pgs.NextOrNew(); pgs.CurrentPage.YOffset = OwnerReport.TopOfPage; if (this.YParents != null) { pi.Y = 0; } } p = pgs.CurrentPage; p.AddObject(pi); // Put image onto the current page RunPageRegionEnd(pgs); if (!this.PageBreakAtEnd && !IsTableOrMatrixCell(rpt)) { float newY = pi.Y + pi.H; p.YOffset += newY; // bump the y location } SetPagePositionEnd(pgs, pi.Y + pi.H); } catch (Exception ex) { rpt.rl.LogError(8, string.Format("Exception in Chart handling.\n{0}\n{1}", ex.Message, ex.StackTrace)); } finally { if (cb != null) { cb.Dispose(); } } return; }
internal List <GroupEntry> Groups; // Runtime groups; array of GroupEntry internal WorkClass(List l) { CalcHeight = l.Height == null? 0: l.Height.Points; Data = null; Groups = null; }