MSChartSeries.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972
  1. using System;
  2. using System.Collections.Generic;
  3. using FastReport.DataVisualization.Charting;
  4. using System.ComponentModel;
  5. using System.Drawing;
  6. using FastReport.Data;
  7. using FastReport.Utils;
  8. using System.Drawing.Design;
  9. namespace FastReport.MSChart
  10. {
  11. /// <summary>
  12. /// Specifies how the series points are sorted.
  13. /// </summary>
  14. public enum SortBy
  15. {
  16. /// <summary>
  17. /// Points are not sorted.
  18. /// </summary>
  19. None,
  20. /// <summary>
  21. /// Points are sorted by X value.
  22. /// </summary>
  23. XValue,
  24. /// <summary>
  25. /// Points are sorted by Y value.
  26. /// </summary>
  27. YValue
  28. }
  29. /// <summary>
  30. /// Specifies the direction in which the series points are sorted.
  31. /// </summary>
  32. public enum ChartSortOrder
  33. {
  34. /// <summary>
  35. /// Points are sorted in ascending order.
  36. /// </summary>
  37. Ascending,
  38. /// <summary>
  39. /// Points are sorted in descending order.
  40. /// </summary>
  41. Descending
  42. }
  43. /// <summary>
  44. /// Specifies how the series points are grouped.
  45. /// </summary>
  46. public enum GroupBy
  47. {
  48. /// <summary>
  49. /// Points are not grouped.
  50. /// </summary>
  51. None,
  52. /// <summary>
  53. /// Points are grouped by X value.
  54. /// </summary>
  55. XValue,
  56. /// <summary>
  57. /// Points are grouped by number specified in the <see cref="MSChartSeries.GroupInterval"/>.
  58. /// </summary>
  59. Number,
  60. /// <summary>
  61. /// Points are grouped by Years.
  62. /// </summary>
  63. Years,
  64. /// <summary>
  65. /// Points are grouped by Months.
  66. /// </summary>
  67. Months,
  68. /// <summary>
  69. /// Points are grouped by Weeks.
  70. /// </summary>
  71. Weeks,
  72. /// <summary>
  73. /// Points are grouped by Days.
  74. /// </summary>
  75. Days,
  76. /// <summary>
  77. /// Points are grouped by Hours.
  78. /// </summary>
  79. Hours,
  80. /// <summary>
  81. /// Points are grouped by Minutes.
  82. /// </summary>
  83. Minutes,
  84. /// <summary>
  85. /// Points are grouped by Seconds.
  86. /// </summary>
  87. Seconds,
  88. /// <summary>
  89. /// Points are grouped by Milliseconds.
  90. /// </summary>
  91. Milliseconds
  92. }
  93. /// <summary>
  94. /// Specifies which pie value to explode.
  95. /// </summary>
  96. public enum PieExplode
  97. {
  98. /// <summary>
  99. /// Do not explode pie values.
  100. /// </summary>
  101. None,
  102. /// <summary>
  103. /// Explode the biggest value.
  104. /// </summary>
  105. BiggestValue,
  106. /// <summary>
  107. /// Explode the lowest value.
  108. /// </summary>
  109. LowestValue,
  110. /// <summary>
  111. /// Explode the value specified in the <see cref="MSChartSeries.PieExplodeValue"/> property.
  112. /// </summary>
  113. SpecificValue
  114. }
  115. /// <summary>
  116. /// Specifies which data points to collect into one point.
  117. /// </summary>
  118. public enum Collect
  119. {
  120. /// <summary>
  121. /// Do not collect points.
  122. /// </summary>
  123. None,
  124. /// <summary>
  125. /// Show top N points (<i>N</i> value is specified in the <see cref="MSChartSeries.CollectValue"/>
  126. /// property), collect other points into one.
  127. /// </summary>
  128. TopN,
  129. /// <summary>
  130. /// Show bottom N points (<i>N</i> value is specified in the <see cref="MSChartSeries.CollectValue"/>
  131. /// property), collect other points into one.
  132. /// </summary>
  133. BottomN,
  134. /// <summary>
  135. /// Collect points which have Y value less than specified
  136. /// in the <see cref="MSChartSeries.CollectValue"/> property.
  137. /// </summary>
  138. LessThan,
  139. /// <summary>
  140. /// Collect points which have Y value less than percent specified
  141. /// in the <see cref="MSChartSeries.CollectValue"/> property.
  142. /// </summary>
  143. LessThanPercent,
  144. /// <summary>
  145. /// Collect points which have Y value greater than specified
  146. /// in the <see cref="MSChartSeries.CollectValue"/> property.
  147. /// </summary>
  148. GreaterThan,
  149. /// <summary>
  150. /// Collect points which have Y value greater than percent specified
  151. /// in the <see cref="MSChartSeries.CollectValue"/> property.
  152. /// </summary>
  153. GreaterThanPercent
  154. }
  155. /// <summary>
  156. /// Represents a MS Chart series wrapper.
  157. /// </summary>
  158. /// <remarks>
  159. /// This class provides a data for MS Chart series. The series itself is stored inside the
  160. /// MS Chart and is accessible via the <see cref="SeriesSettings"/> property.
  161. /// <para/>You don't need to create an instance of this class directly. Instead, use the
  162. /// <see cref="MSChartObject.AddSeries"/> method.
  163. /// </remarks>
  164. public class MSChartSeries : Base
  165. {
  166. #region Fields
  167. private string filter;
  168. private SortBy sortBy;
  169. private ChartSortOrder sortOrder;
  170. private GroupBy groupBy;
  171. private float groupInterval;
  172. private TotalType groupFunction;
  173. private Collect collect;
  174. private float collectValue;
  175. private string collectedItemText;
  176. private Color collectedItemColor;
  177. private PieExplode pieExplode;
  178. private string pieExplodeValue;
  179. private string xValue;
  180. private string yValue1;
  181. private string yValue2;
  182. private string yValue3;
  183. private string yValue4;
  184. private string color;
  185. private string label;
  186. private bool autoSeriesForce;
  187. private string autoSeriesColumn;
  188. #endregion
  189. #region Properties
  190. /// <summary>
  191. /// Gets os sets the data filter expression.
  192. /// </summary>
  193. /// <remarks>
  194. /// The filter is applied for this series only. You can also use the
  195. /// <see cref="MSChartObject.Filter"/> property to set a filter that will be applied to all
  196. /// series in a chart.
  197. /// </remarks>
  198. [Category("Data")]
  199. [Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))]
  200. public string Filter
  201. {
  202. get { return filter; }
  203. set { filter = value; }
  204. }
  205. /// <summary>
  206. /// Gets or set the data column or expression for automatically created series.
  207. /// </summary>
  208. /// <remarks>
  209. /// In order to create auto-series, you need to define one series that will be used as a
  210. /// template for new series, and set up the <see cref="AutoSeriesColumn"/> property.
  211. /// The value of this property will be a name of new series. If there is no series
  212. /// with such name yet, the new series will be added.
  213. /// </remarks>
  214. [Category("Data")]
  215. [Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))]
  216. public string AutoSeriesColumn
  217. {
  218. get { return autoSeriesColumn; }
  219. set { autoSeriesColumn = value; }
  220. }
  221. /// <summary>
  222. /// Gets or sets the sort method used to sort data points.
  223. /// </summary>
  224. /// <remarks>
  225. /// You have to specify the <see cref="SortOrder"/> property as well. Data points in this series
  226. /// will be sorted according selected sort criteria and order.
  227. /// </remarks>
  228. [Category("Data")]
  229. [DefaultValue(SortBy.None)]
  230. public SortBy SortBy
  231. {
  232. get { return sortBy; }
  233. set { sortBy = value; }
  234. }
  235. /// <summary>
  236. /// Gets or set Force automatically created series.
  237. /// </summary>
  238. [Category("Data")]
  239. [DefaultValue(true)]
  240. public bool AutoSeriesForce
  241. {
  242. get { return autoSeriesForce; }
  243. set { autoSeriesForce = value; }
  244. }
  245. /// <summary>
  246. /// Gets or sets the sort order used to sort data points.
  247. /// </summary>
  248. /// <remarks>
  249. /// You have to specify the <see cref="SortBy"/> property as well. Data points in this series
  250. /// will be sorted according selected sort criteria and order.
  251. /// </remarks>
  252. [Category("Data")]
  253. [DefaultValue(ChartSortOrder.Ascending)]
  254. public ChartSortOrder SortOrder
  255. {
  256. get { return sortOrder; }
  257. set { sortOrder = value; }
  258. }
  259. /// <summary>
  260. /// Gets or sets the group method used to group data points.
  261. /// </summary>
  262. /// <remarks>
  263. /// This property is mainly used when series is filled with data with several identical X values.
  264. /// In this case, you need to set the property to <b>XValue</b>. All identical data points will be
  265. /// grouped into one point, their Y values will be summarized. You can choose the summary function
  266. /// using the <see cref="GroupFunction"/> property.
  267. /// </remarks>
  268. [Category("Data")]
  269. [DefaultValue(GroupBy.None)]
  270. public GroupBy GroupBy
  271. {
  272. get { return groupBy; }
  273. set { groupBy = value; }
  274. }
  275. /// <summary>
  276. /// Gets or sets the group interval.
  277. /// </summary>
  278. /// <remarks>
  279. /// This value is used if <see cref="GroupBy"/> property is set to <b>Number</b>.
  280. /// </remarks>
  281. [Category("Data")]
  282. [DefaultValue(1f)]
  283. public float GroupInterval
  284. {
  285. get { return groupInterval; }
  286. set { groupInterval = value; }
  287. }
  288. /// <summary>
  289. /// Gets or sets the function used to group data points.
  290. /// </summary>
  291. [Category("Data")]
  292. [DefaultValue(TotalType.Sum)]
  293. public TotalType GroupFunction
  294. {
  295. get { return groupFunction; }
  296. set { groupFunction = value; }
  297. }
  298. /// <summary>
  299. /// Gets or sets the collect method used to collect several data points into one.
  300. /// </summary>
  301. /// <remarks>
  302. /// This instrument for data processing allows to collect several series points into one point.
  303. /// The collected point will be displaed using the text specified in the <see cref="CollectedItemText"/>
  304. /// property and color specified in the <see cref="CollectedItemColor"/> property.
  305. /// <para/>For example, to display top 5 values, set this property to <b>TopN</b> and specify
  306. /// N value (5) in the <see cref="CollectValue"/> property.
  307. /// </remarks>
  308. [Category("Data")]
  309. [DefaultValue(Collect.None)]
  310. public Collect Collect
  311. {
  312. get { return collect; }
  313. set { collect = value; }
  314. }
  315. /// <summary>
  316. /// Gets or sets the collect value used to collect several data points into one.
  317. /// </summary>
  318. /// <remarks>
  319. /// This property is used if the <see cref="Collect"/> property is set to any value other than <b>None</b>.
  320. /// </remarks>
  321. [Category("Data")]
  322. [DefaultValue(0f)]
  323. public float CollectValue
  324. {
  325. get { return collectValue; }
  326. set { collectValue = value; }
  327. }
  328. /// <summary>
  329. /// Gets or sets the text for the collected value.
  330. /// </summary>
  331. [Category("Data")]
  332. public string CollectedItemText
  333. {
  334. get { return collectedItemText; }
  335. set { collectedItemText = value; }
  336. }
  337. /// <summary>
  338. /// Gets or sets the color for the collected value.
  339. /// </summary>
  340. /// <remarks>
  341. /// If this property is set to <b>Transparent</b> (by default), the default palette color
  342. /// will be used to display a collected point.
  343. /// </remarks>
  344. [Category("Data")]
  345. public Color CollectedItemColor
  346. {
  347. get { return collectedItemColor; }
  348. set { collectedItemColor = value; }
  349. }
  350. /// <summary>
  351. /// Gets or sets the method used to explode values in pie-type series.
  352. /// </summary>
  353. [Category("Data")]
  354. [DefaultValue(PieExplode.None)]
  355. public PieExplode PieExplode
  356. {
  357. get { return pieExplode; }
  358. set { pieExplode = value; }
  359. }
  360. /// <summary>
  361. /// Gets or sets the value that must be exploded.
  362. /// </summary>
  363. /// <remarks>
  364. /// This property is used if <see cref="PieExplode"/> property is set
  365. /// to <b>SpecificValue</b>.
  366. /// </remarks>
  367. [Category("Data")]
  368. [Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))]
  369. public string PieExplodeValue
  370. {
  371. get { return pieExplodeValue; }
  372. set { pieExplodeValue = value; }
  373. }
  374. /// <summary>
  375. /// Gets or sets the data column or expression that returns the X value of data point.
  376. /// </summary>
  377. [Category("Data")]
  378. [Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))]
  379. public string XValue
  380. {
  381. get { return xValue; }
  382. set { xValue = value; }
  383. }
  384. /// <summary>
  385. /// Gets or sets the data column or expression that returns the first Y value of data point.
  386. /// </summary>
  387. [Category("Data")]
  388. [Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))]
  389. public string YValue1
  390. {
  391. get { return yValue1; }
  392. set { yValue1 = value; }
  393. }
  394. /// <summary>
  395. /// Gets or sets the data column or expression returns the second Y value of data point.
  396. /// </summary>
  397. [Category("Data")]
  398. [Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))]
  399. public string YValue2
  400. {
  401. get { return yValue2; }
  402. set { yValue2 = value; }
  403. }
  404. /// <summary>
  405. /// Gets or sets the data column or expression returns the third Y value of data point.
  406. /// </summary>
  407. [Category("Data")]
  408. [Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))]
  409. public string YValue3
  410. {
  411. get { return yValue3; }
  412. set { yValue3 = value; }
  413. }
  414. /// <summary>
  415. /// Gets or sets the data column or expression returns the fourth Y value of data point.
  416. /// </summary>
  417. [Category("Data")]
  418. [Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))]
  419. public string YValue4
  420. {
  421. get { return yValue4; }
  422. set { yValue4 = value; }
  423. }
  424. /// <summary>
  425. /// Gets or sets the data column or expression that returns the color of data point.
  426. /// </summary>
  427. [Category("Data")]
  428. [Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))]
  429. public string Color
  430. {
  431. get { return color; }
  432. set { color = value; }
  433. }
  434. /// <summary>
  435. /// Gets or sets the data column or expression returns the label value of data point.
  436. /// </summary>
  437. [Category("Data")]
  438. [Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))]
  439. public string Label
  440. {
  441. get { return label; }
  442. set { label = value; }
  443. }
  444. /// <summary>
  445. /// Gets a reference to MS Chart <b>Series</b> object.
  446. /// </summary>
  447. /// <remarks>
  448. /// Use this property to set many options available for the <b>Series</b> object. These options
  449. /// include: visual appearance, labels, marks, value types. Refer to the Microsoft Chart control
  450. /// documentation to learn more.
  451. /// </remarks>
  452. [Category("Appearance")]
  453. public Series SeriesSettings
  454. {
  455. get
  456. {
  457. MSChartObject parent = Parent as MSChartObject;
  458. if (parent == null)
  459. return null;
  460. int index = parent.Series.IndexOf(this);
  461. if (index < parent.Chart.Series.Count)
  462. return parent.Chart.Series[index];
  463. return null;
  464. }
  465. }
  466. /// <summary>
  467. /// Gets a number of Y value per data point.
  468. /// </summary>
  469. /// <remarks>
  470. /// Number of Y values depends on series type. Most of series have only one Y value. Financial
  471. /// series such as Stock and Candlestick, use four Y values.
  472. /// </remarks>
  473. [Browsable(false)]
  474. public int YValuesPerPoint
  475. {
  476. get { return SeriesSettings.YValuesPerPoint; }
  477. }
  478. /// <summary>
  479. /// This property is not relevant to this class.
  480. /// </summary>
  481. [Browsable(false)]
  482. public new Restrictions Restrictions
  483. {
  484. get { return base.Restrictions; }
  485. set { base.Restrictions = value; }
  486. }
  487. #endregion
  488. #region Private Methods
  489. private object Calc(string expression)
  490. {
  491. if (!String.IsNullOrEmpty(expression))
  492. return Report.Calc(expression);
  493. return null;
  494. }
  495. private void InternalProcessData()
  496. {
  497. object xValue = Calc(XValue);
  498. if (xValue != null)
  499. {
  500. string[] expressions = new string[] { YValue1, YValue2, YValue3, YValue4 };
  501. object[] values = new object[YValuesPerPoint];
  502. for (int i = 0; i < YValuesPerPoint; i++)
  503. {
  504. values[i] = Calc(expressions[i]);
  505. }
  506. DataPoint point = SeriesSettings.Points[SeriesSettings.Points.AddXY(xValue, values)];
  507. // color
  508. object color = Calc(Color);
  509. if (color != null)
  510. {
  511. if (color is System.Drawing.Color)
  512. point.Color = (System.Drawing.Color)color;
  513. else if (color is Int32)
  514. point.Color = System.Drawing.Color.FromArgb(255, System.Drawing.Color.FromArgb((int)color));
  515. else if (color is String)
  516. point.Color = System.Drawing.Color.FromName((string)color);
  517. }
  518. // label
  519. object label = Calc(Label);
  520. if (label != null)
  521. point.Label = label.ToString();
  522. }
  523. }
  524. private void SortData()
  525. {
  526. SeriesSettings.Sort(new DataPointComparer(SortBy, SortOrder));
  527. }
  528. private void CollectValues()
  529. {
  530. double others = 0;
  531. if (Collect == Collect.TopN || Collect == Collect.BottomN)
  532. {
  533. for (int i = (int)CollectValue; i < SeriesSettings.Points.Count;)
  534. {
  535. others += SeriesSettings.Points[i].YValues[0];
  536. SeriesSettings.Points.RemoveAt(i);
  537. }
  538. }
  539. else
  540. {
  541. double totalValue = 0;
  542. if (Collect == Collect.LessThanPercent || Collect == Collect.GreaterThanPercent)
  543. {
  544. foreach (DataPoint point in SeriesSettings.Points)
  545. {
  546. totalValue += point.YValues[0];
  547. }
  548. }
  549. for (int i = 0; i < SeriesSettings.Points.Count;)
  550. {
  551. double value = SeriesSettings.Points[i].YValues[0];
  552. if ((Collect == Collect.LessThan && value < CollectValue) ||
  553. (Collect == Collect.GreaterThan && value > CollectValue) ||
  554. (Collect == Collect.LessThanPercent && value / totalValue * 100 < CollectValue) ||
  555. (Collect == Collect.GreaterThanPercent && value / totalValue * 100 > CollectValue))
  556. {
  557. others += value;
  558. SeriesSettings.Points.RemoveAt(i);
  559. }
  560. else
  561. i++;
  562. }
  563. }
  564. if (others > 0 && !String.IsNullOrEmpty(CollectedItemText))
  565. {
  566. SeriesSettings.Points.AddXY(CollectedItemText, others);
  567. DataPoint point = SeriesSettings.Points[SeriesSettings.Points.Count - 1];
  568. if (CollectedItemColor != System.Drawing.Color.Transparent)
  569. point.Color = CollectedItemColor;
  570. }
  571. }
  572. private void GroupData()
  573. {
  574. Chart chart = (Parent as MSChartObject).Chart;
  575. string function = "";
  576. switch (GroupFunction)
  577. {
  578. case TotalType.Sum:
  579. function = "SUM";
  580. break;
  581. case TotalType.Min:
  582. function = "MIN";
  583. break;
  584. case TotalType.Max:
  585. function = "MAX";
  586. break;
  587. case TotalType.Avg:
  588. function = "AVE";
  589. break;
  590. case TotalType.Count:
  591. function = "COUNT";
  592. break;
  593. }
  594. if (GroupBy == GroupBy.XValue)
  595. chart.DataManipulator.GroupByAxisLabel(function, SeriesSettings);
  596. else
  597. {
  598. IntervalType type = IntervalType.Number;
  599. switch (GroupBy)
  600. {
  601. case GroupBy.Years:
  602. type = IntervalType.Years;
  603. break;
  604. case GroupBy.Months:
  605. type = IntervalType.Months;
  606. break;
  607. case GroupBy.Weeks:
  608. type = IntervalType.Weeks;
  609. break;
  610. case GroupBy.Days:
  611. type = IntervalType.Days;
  612. break;
  613. case GroupBy.Hours:
  614. type = IntervalType.Hours;
  615. break;
  616. case GroupBy.Minutes:
  617. type = IntervalType.Minutes;
  618. break;
  619. case GroupBy.Seconds:
  620. type = IntervalType.Seconds;
  621. break;
  622. case GroupBy.Milliseconds:
  623. type = IntervalType.Milliseconds;
  624. break;
  625. }
  626. chart.DataManipulator.Group(function, GroupInterval, type, SeriesSettings);
  627. }
  628. }
  629. private void ExplodePoint()
  630. {
  631. if (SeriesSettings.Points.Count == 0)
  632. return;
  633. if (PieExplode == PieExplode.SpecificValue)
  634. {
  635. object pieExplodeValue = Calc(PieExplodeValue);
  636. if (pieExplodeValue != null)
  637. {
  638. foreach (DataPoint point in SeriesSettings.Points)
  639. {
  640. if (point.AxisLabel == pieExplodeValue.ToString())
  641. {
  642. point["Exploded"] = "true";
  643. break;
  644. }
  645. }
  646. }
  647. }
  648. else
  649. {
  650. List<DataPoint> points = new List<DataPoint>();
  651. foreach (DataPoint point in SeriesSettings.Points)
  652. {
  653. points.Add(point);
  654. }
  655. points.Sort(new DataPointComparer(SortBy.YValue, ChartSortOrder.Ascending));
  656. DataPoint explodePoint = null;
  657. if (PieExplode == PieExplode.BiggestValue)
  658. explodePoint = points[points.Count - 1];
  659. else
  660. explodePoint = points[0];
  661. explodePoint["Exploded"] = "true";
  662. }
  663. }
  664. #endregion
  665. #region Public Methods
  666. /// <inheritdoc/>
  667. public override void Assign(Base source)
  668. {
  669. base.Assign(source);
  670. MSChartSeries src = source as MSChartSeries;
  671. Filter = src.Filter;
  672. SortOrder = src.SortOrder;
  673. SortBy = src.SortBy;
  674. GroupBy = src.GroupBy;
  675. GroupInterval = src.GroupInterval;
  676. GroupFunction = src.GroupFunction;
  677. Collect = src.Collect;
  678. CollectValue = src.CollectValue;
  679. CollectedItemText = src.CollectedItemText;
  680. CollectedItemColor = src.CollectedItemColor;
  681. PieExplode = src.PieExplode;
  682. PieExplodeValue = src.PieExplodeValue;
  683. AutoSeriesForce = src.AutoSeriesForce;
  684. AutoSeriesColumn = src.AutoSeriesColumn;
  685. XValue = src.XValue;
  686. YValue1 = src.YValue1;
  687. YValue2 = src.YValue2;
  688. YValue3 = src.YValue3;
  689. YValue4 = src.YValue4;
  690. Color = src.Color;
  691. Label = src.Label;
  692. }
  693. /// <inheritdoc/>
  694. public override void Serialize(FRWriter writer)
  695. {
  696. MSChartSeries s = writer.DiffObject as MSChartSeries;
  697. base.Serialize(writer);
  698. if (Filter != s.Filter)
  699. writer.WriteStr("Filter", Filter);
  700. if (SortOrder != s.SortOrder)
  701. writer.WriteValue("SortOrder", SortOrder);
  702. if (SortBy != s.SortBy)
  703. writer.WriteValue("SortBy", SortBy);
  704. if (GroupBy != s.GroupBy)
  705. writer.WriteValue("GroupBy", GroupBy);
  706. if (GroupInterval != s.GroupInterval)
  707. writer.WriteFloat("GroupInterval", GroupInterval);
  708. if (GroupFunction != s.GroupFunction)
  709. writer.WriteValue("GroupFunction", GroupFunction);
  710. if (Collect != s.Collect)
  711. writer.WriteValue("Collect", Collect);
  712. if (CollectValue != s.CollectValue)
  713. writer.WriteFloat("CollectValue", CollectValue);
  714. if (CollectedItemText != s.CollectedItemText)
  715. writer.WriteStr("CollectedItemText", CollectedItemText);
  716. if (CollectedItemColor != s.CollectedItemColor)
  717. writer.WriteValue("CollectedItemColor", CollectedItemColor);
  718. if (PieExplode != s.PieExplode)
  719. writer.WriteValue("PieExplode", PieExplode);
  720. if (PieExplodeValue != s.PieExplodeValue)
  721. writer.WriteStr("PieExplodeValue", PieExplodeValue);
  722. if (XValue != s.XValue)
  723. writer.WriteStr("XValue", XValue);
  724. if (YValue1 != s.YValue1)
  725. writer.WriteStr("YValue1", YValue1);
  726. if (YValue2 != s.YValue2)
  727. writer.WriteStr("YValue2", YValue2);
  728. if (YValue3 != s.YValue3)
  729. writer.WriteStr("YValue3", YValue3);
  730. if (YValue4 != s.YValue4)
  731. writer.WriteStr("YValue4", YValue4);
  732. if (Color != s.Color)
  733. writer.WriteStr("Color", Color);
  734. if (Label != s.Label)
  735. writer.WriteStr("Label", Label);
  736. if (!AutoSeriesForce)
  737. writer.WriteBool("AutoSeriesForce", AutoSeriesForce);
  738. if (AutoSeriesColumn != s.AutoSeriesColumn)
  739. writer.WriteStr("AutoSeriesColumn", AutoSeriesColumn);
  740. }
  741. /// <inheritdoc/>
  742. public override void Deserialize(FRReader reader)
  743. {
  744. base.Deserialize(reader);
  745. if (reader.HasProperty("GroupByXValue"))
  746. GroupBy = GroupBy.XValue;
  747. }
  748. /// <summary>
  749. /// Clears all data points in this series.
  750. /// </summary>
  751. public void ClearValues()
  752. {
  753. SeriesSettings.Points.Clear();
  754. }
  755. /// <summary>
  756. /// Adds a data point with specified X and Y values.
  757. /// </summary>
  758. /// <param name="xValue">X value.</param>
  759. /// <param name="yValues">Array of Y values.</param>
  760. /// <remarks>
  761. /// Note: number of values in the <b>yValues</b> parameter must be the same as value returned
  762. /// by the <see cref="YValuesPerPoint"/> property.
  763. /// </remarks>
  764. public void AddValue(object xValue, params object[] yValues)
  765. {
  766. SeriesSettings.Points.AddXY(xValue, yValues);
  767. }
  768. internal void ProcessData()
  769. {
  770. object match = true;
  771. if (!String.IsNullOrEmpty(Filter))
  772. match = Report.Calc(Filter);
  773. if (match is bool && (bool)match == true)
  774. InternalProcessData();
  775. }
  776. internal void FinishData()
  777. {
  778. // sort is required if we group by value, not by axis label
  779. bool sortThenGroup = GroupBy != GroupBy.XValue;
  780. if (!sortThenGroup)
  781. {
  782. if (GroupBy != GroupBy.None)
  783. GroupData();
  784. }
  785. // sort
  786. if (Collect == Collect.TopN)
  787. {
  788. SortBy = SortBy.YValue;
  789. SortOrder = ChartSortOrder.Descending;
  790. }
  791. else if (Collect == Collect.BottomN)
  792. {
  793. SortBy = SortBy.YValue;
  794. SortOrder = ChartSortOrder.Ascending;
  795. }
  796. if (SortBy != SortBy.None)
  797. SortData();
  798. // group
  799. if (sortThenGroup)
  800. {
  801. if (GroupBy != GroupBy.None)
  802. GroupData();
  803. }
  804. // collect topn values
  805. if (Collect != Collect.None)
  806. CollectValues();
  807. // explode values
  808. if (PieExplode != PieExplode.None)
  809. ExplodePoint();
  810. }
  811. internal void CreateDummyData()
  812. {
  813. SeriesSettings.Points.Clear();
  814. SeriesSettings.Points.AddXY("A", 1);
  815. SeriesSettings.Points.AddXY("B", 3);
  816. SeriesSettings.Points.AddXY("C", 2);
  817. SeriesSettings.Points.AddXY("D", 4);
  818. }
  819. /// <inheritdoc/>
  820. public override string[] GetExpressions()
  821. {
  822. List<string> expressions = new List<string>();
  823. if (!String.IsNullOrEmpty(PieExplodeValue))
  824. expressions.Add(PieExplodeValue);
  825. if (!String.IsNullOrEmpty(XValue))
  826. expressions.Add(XValue);
  827. if (!String.IsNullOrEmpty(YValue1))
  828. expressions.Add(YValue1);
  829. if (!String.IsNullOrEmpty(YValue2))
  830. expressions.Add(YValue2);
  831. if (!String.IsNullOrEmpty(YValue3))
  832. expressions.Add(YValue3);
  833. if (!String.IsNullOrEmpty(YValue4))
  834. expressions.Add(YValue4);
  835. if (!String.IsNullOrEmpty(Color))
  836. expressions.Add(Color);
  837. if (!String.IsNullOrEmpty(Label))
  838. expressions.Add(Label);
  839. if (!String.IsNullOrEmpty(Filter))
  840. expressions.Add(Filter);
  841. return expressions.ToArray();
  842. }
  843. #endregion
  844. /// <summary>
  845. /// Creates a new instance of the <see cref="MSChartSeries"/> class with default settings.
  846. /// </summary>
  847. public MSChartSeries()
  848. {
  849. filter = "";
  850. groupInterval = 1;
  851. collectedItemText = "";
  852. collectedItemColor = System.Drawing.Color.Transparent;
  853. pieExplodeValue = "";
  854. xValue = "";
  855. yValue1 = "";
  856. yValue2 = "";
  857. yValue3 = "";
  858. yValue4 = "";
  859. color = "";
  860. label = "";
  861. autoSeriesForce = true;
  862. BaseName = "Series";
  863. }
  864. }
  865. }