记得2010年之前,公司的项目基本上都要用到报表,以前我们常用的方法就是针对客户的需求来定制化开发(基本上是死写代码)来实现,经常导致项目经常性的延期,因为客户的需求经常会变化,随着用户的使用认知度的提高,对报表的要求越来越高,导致程序员不停的修改代码来实现,效率不高、结束遥遥无期。。。非常的痛苦;当然市面上有很多报表开发工具可以实现,但是针对小公司来说采购一套这样的系统的成本也非常的高,所以我们决定自己来开发一套像目前的润乾、FineReport 这样的报表设计器,来实现快速的报表设计制作。

当初为了开发这样的系统,花费的了很长的时间学习查阅各种资料,其痛苦只有程序员才能体会,因为没有任何现成的实例代码可供参考,只有看别人的思路来一步步的摸索,本文将我们当初设计制作的报表设计器的功能分享出来,让有需要的或想开发报表设计的朋友们提供一个参考,尽量少走很动弯路,设计端可以直接使用,但是计算引擎和网页的计算的源码就不能分享出来了(请不要介意,因为涉及到公司的保密原因)

记得当初为了制作报表设计器,在网上查找有没有相关的实例资料,找了很久,也是没有找到合适的,后来发现 SourceGrid 可以实现单元格的合并拆分功能,所以决定修改实现winform端的报表设计。下面我将制作的E_Report 报表控件抽取出来建立一个简易的Winform的可运行的实例提供给大伙下载,希望能给你的开发提供一点帮助和借鉴;当然你可以直接使用也可以,里面的设计功能基本全部能。

抽取出来的源码包含:E_Report 报表设计自定义控件DLL源码;  EReportDemo 建立的简易Winform 端设计器使用DLL的实例源码;

一、运行效果

实例中,只做了一个简单的效果,工具栏的按钮在单元格右击属性中都有,只是放了几个常用的在工具导航栏中(右击单元格属性可以看到设计导航)

可以进行单元格的合并、拆分、字体、颜色、背景、边框等的设置,朋友们可以自己编写保存发布等功能,实现报表的真实功能;

例如单元格属性(其他还有很多的属性,自己下载源码后运行起来就能看到了)

对表格的斜线、斜线文字有很好的支持;可以设置表头、表位、标题等 实际效果图如下

二、使用介绍

1、页面初始化的时候,通过 ReportDoc 类 初始报表的行列及单元格属性

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Drawing;
  5. using System.Windows.Forms;
  6. using System.Drawing.Drawing2D;
  7. using System.Xml;
  8. using System.Collections;
  9. using E_Report;
  10.  
  11. namespace EReportDemo
  12. {
  13. /// <summary>
  14. /// 报表表格对象
  15. /// </summary>
  16. public class ReportDoc
  17. {
  18. #region 变量参数定义
  19.  
  20. /// <summary>
  21. /// 表格对象
  22. /// </summary>
  23. private EReport _nowReport;
  24.  
  25. /// <summary>
  26. /// 报表配置编码
  27. /// </summary>
  28. private string _reportCode = "";
  29.  
  30. /// <summary>
  31. /// 表报设计状态
  32. /// </summary>
  33. private string _reportState = "";
  34.  
  35. #endregion
  36.  
  37. #region 函数构造方法
  38.  
  39. /// <summary>
  40. /// 构造函数
  41. /// </summary>
  42. public ReportDoc()
  43. {
  44. this._nowReport = null;
  45. this._reportCode = "";
  46. this._reportState = "";
  47.  
  48. }
  49.  
  50. /// <summary>
  51. /// 获取--设置--表格对象
  52. /// </summary>
  53. public EReport NowReport
  54. {
  55. get { return this._nowReport; }
  56. set { this._nowReport = value; }
  57. }
  58.  
  59. /// <summary>
  60. /// 报表配置编码
  61. /// </summary>
  62. public string ReportCode
  63. {
  64. get { return this._reportCode; }
  65. set { this._reportCode = value; }
  66. }
  67.  
  68. /// <summary>
  69. /// 报表设计状态
  70. /// 新增、修改 两种状态
  71. /// </summary>
  72. public string ReportState
  73. {
  74. get { return this._reportState; }
  75. set { this._reportState = value; }
  76. }
  77.  
  78. /// <summary>
  79. /// 资源释放
  80. /// </summary>
  81. ~ReportDoc()
  82. {
  83. this._nowReport = null;
  84. this._reportState = "";
  85.  
  86. }
  87.  
  88. #endregion
  89.  
  90. #region 加载报表表格
  91.  
  92. /// <summary>
  93. /// 初始化--报表表格
  94. /// </summary>
  95. public void InitReport()
  96. {
  97.  
  98. int rCount = ; // 41行
  99. int cCount = ; // 20列
  100.  
  101. _nowReport.Redim(rCount, cCount);
  102. _nowReport.FixedRows = ;
  103. _nowReport.FixedColumns = ;
  104.  
  105. InitCells();
  106.  
  107. }
  108.  
  109. /// <summary>
  110. /// 初始化--单元格
  111. /// </summary>
  112. public void InitCells()
  113. {
  114. // 第一行 第一列
  115. _nowReport.Rows[].Height = ;
  116. _nowReport.Columns[].Width = ;
  117.  
  118. // 设置00格
  119. _nowReport[, ] = new E_Report.Cells.HeaderColumn("");
  120.  
  121. // 设置行
  122. for (int rr = ; rr < _nowReport.RowsCount; rr++)
  123. {
  124. string tmRowT = rr.ToString();
  125. _nowReport[rr, ] = new E_Report.Cells.HeaderRow(tmRowT);
  126. }
  127.  
  128. // 设置列
  129. for (int cc = ; cc < _nowReport.ColumnsCount; cc++)
  130. {
  131. _nowReport[, cc] = new E_Report.Cells.HeaderColumn(_nowReport.GetColumnHeadTileChar(cc));
  132. }
  133.  
  134. // 设置单元格
  135. for (int iRow = ; iRow < _nowReport.RowsCount; iRow++)
  136. {
  137. for (int iCol = ; iCol < _nowReport.ColumnsCount; iCol++)
  138. {
  139. _nowReport[iRow, iCol] = new E_Report.Cells.Cell("", typeof(string));
  140. }
  141. }
  142.  
  143. }
  144.  
  145. #endregion
  146.  
  147. }
  148. }

2、工具导航栏 设置单元格相关属性

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Text;
  7. using System.Windows.Forms;
  8. using System.Collections;
  9. using E_Report;
  10.  
  11. namespace EReportDemo
  12. {
  13. /// <summary>
  14. /// 本程序只是Winform端的报表设计功能
  15. /// 至于其他的功能,本实例没有提供
  16. /// 报表设计的设计效果:可以查看 www.sdpsoft.com SDP软件快速开发平台 报表设计篇
  17. /// </summary>
  18.  
  19. public partial class EReportMain : Form
  20. {
  21. private ReportDoc report;
  22. private E_Report.Cells.Controllers.PopupMenu myPopupMenu;
  23.  
  24. public EReportMain()
  25. {
  26. InitializeComponent();
  27. }
  28.  
  29. private void EReportMain_Load(object sender, EventArgs e)
  30. {
  31. Cursor.Current = Cursors.WaitCursor;
  32. gridMain.Rows.Clear();
  33. myPopupMenu = new E_Report.Cells.Controllers.PopupMenu(gridMain);
  34.  
  35. report = new ReportDoc();
  36. report.NowReport = gridMain;
  37. report.InitReport();
  38. Cursor.Current = Cursors.Default;
  39. }
  40.  
  41. private void gridMain_MouseMove(object sender, MouseEventArgs e)
  42. {
  43. this.lbl_X.Text = e.X.ToString();
  44. this.lbl_Y.Text = e.Y.ToString();
  45. }
  46.  
  47. /// <summary>
  48. /// 工具栏报表单元格事件
  49. /// </summary>
  50. /// <param name="sender"></param>
  51. /// <param name="e"></param>
  52. private void btn_GridTools_Click(object sender, EventArgs e)
  53. {
  54. string sType = ((Button)sender).Tag.ToString().Trim().ToLower();
  55. switch (sType)
  56. {
  57.  
  58. case "cellproperty": // 单元格属性设置
  59. myPopupMenu.CellProperty_Click(sender, e);
  60. break;
  61. case "fontset": // 单元格字体设置
  62. myPopupMenu.CellFont_Click(sender, e);
  63. break;
  64. case "fontcolor": // 文本字体颜色
  65. myPopupMenu.CellForColor_Click(sender, e);
  66. break;
  67. case "backcolor": // 单元格背景色
  68. myPopupMenu.CellBackColor_Click(sender, e);
  69. break;
  70. case "cellborder": // 单元格边框设置
  71. myPopupMenu.CellBorder_Click(sender, e);
  72. break;
  73. case "lock": // 设置表格只读
  74. myPopupMenu.LockReport_Click(sender, e);
  75. break;
  76. case "unlock": // 设置表格编辑
  77. myPopupMenu.UnLockReport_Click(sender, e);
  78. break;
  79. case "alignleft": // 水平居左对齐
  80. myPopupMenu.AlignLeft_Click(sender, e);
  81. break;
  82. case "aligncenter": // 水平居中对齐
  83. myPopupMenu.AlignCenter_Click(sender, e);
  84. break;
  85. case "alignright": // 水平居右对齐
  86. myPopupMenu.AlignRight_Click(sender, e);
  87. break;
  88. case "aligntop": // 垂直居上对齐
  89. myPopupMenu.AlignTop_Click(sender, e);
  90. break;
  91. case "alignmiddle": // 垂直居中对齐
  92. myPopupMenu.AlignMiddle_Click(sender, e);
  93. break;
  94. case "alignbottom": // 垂直居下对齐
  95. myPopupMenu.AlignBottom_Click(sender, e);
  96. break;
  97. case "addindent": // 增加文本缩进
  98. myPopupMenu.AddIndent_Click(sender, e);
  99. break;
  100. case "delindent": // 清除文本缩进
  101. myPopupMenu.RemoveIndent_Click(sender, e);
  102. break;
  103. case "insertrow": // 插入后一行
  104. myPopupMenu.InsertRow_Click(sender, e);
  105. break;
  106. case "appendrow": // 表格追加行
  107. myPopupMenu.AddRow_Click(sender, e);
  108. break;
  109. case "delrow": // 删除选中行
  110. myPopupMenu.DeleteRows_Click(sender, e);
  111. break;
  112. case "hiderow": // 隐藏选中行
  113. myPopupMenu.HideSelectRows_Click(sender, e);
  114. break;
  115. case "showrow": // 显示选中行
  116. myPopupMenu.ShowSelectRows_Click(sender, e);
  117. break;
  118. case "showallrow": // 显示所有行
  119. myPopupMenu.ShowAllRows_Click(sender, e);
  120. break;
  121. case "insertcol": // 插入左侧列
  122. myPopupMenu.InsertColumn_Click(sender, e);
  123. break;
  124. case "addcol": // 插入右侧列
  125. myPopupMenu.AddColumn_Click(sender, e);
  126. break;
  127. case "delcol": // 删除选中列
  128. myPopupMenu.DeleteColumns_Click(sender, e);
  129. break;
  130. case "hidecol": // 隐藏选中列
  131. myPopupMenu.HideSelectColumns_Click(sender, e);
  132. break;
  133. case "showcol": // 显示选中列
  134. myPopupMenu.ShowSelectColumns_Click(sender, e);
  135. break;
  136. case "showallcol": // 显示所有列
  137. myPopupMenu.ShowAllColumns_Click(sender, e);
  138. break;
  139. case "mergecell": // 合并单元格
  140. myPopupMenu.MergeCell_Click(sender, e);
  141. break;
  142. case "splitcell": // 拆分单元格
  143. myPopupMenu.SplitCell_Click(sender, e);
  144. break;
  145. }
  146. }
  147. }
  148. }

3、报表控件DLL类库部分

里面有我们自定义的 条码控件、图片控件、图表控件

表格内自定义图表控件(曲线、柱状、饼状)源码

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Drawing;
  5. using System.Drawing.Drawing2D;
  6. using System.Drawing.Text;
  7.  
  8. namespace E_Report
  9. {
  10. /// <summary>
  11. /// 图表属性
  12. /// </summary>
  13. /// <summary>
  14. /// 报表图表类库
  15. /// </summary>
  16. public class EChart
  17. {
  18. #region 属性方法
  19.  
  20. #region 临时变量
  21.  
  22. /// <summary>
  23. /// 临时变量--关联单元格行号
  24. /// </summary>
  25. private int _row = ;
  26.  
  27. /// <summary>
  28. /// 获取--设置--关联单元格行号
  29. /// </summary>
  30. public int Row
  31. {
  32. get { return _row; }
  33. set { _row = value; }
  34. }
  35.  
  36. /// <summary>
  37. /// 临时变量--关联单元格列号
  38. /// </summary>
  39. private int _col = ;
  40.  
  41. /// <summary>
  42. /// 获取--设置--关联单元格列号
  43. /// </summary>
  44. public int Col
  45. {
  46. get { return _col; }
  47. set { _col = value; }
  48. }
  49.  
  50. /// <summary>
  51. /// 数据来源
  52. /// </summary>
  53. private string _t_DataFrom = "数据源";
  54.  
  55. /// <summary>
  56. /// 获取--设置--数据来源
  57. /// </summary>
  58. public string T_DataFrom
  59. {
  60. get { return _t_DataFrom; }
  61. set { _t_DataFrom = value; }
  62. }
  63.  
  64. /// <summary>
  65. /// 数据源名称
  66. /// </summary>
  67. private string _t_DsName = "";
  68.  
  69. /// <summary>
  70. /// 获取--设置--数据源名称
  71. /// </summary>
  72. public string T_DsName
  73. {
  74. get { return _t_DsName; }
  75. set { _t_DsName = value; }
  76. }
  77.  
  78. /// <summary>
  79. /// 项目名称
  80. /// </summary>
  81. private string _t_ItemName = "";
  82.  
  83. /// <summary>
  84. /// 获取--设置--项目名称
  85. /// </summary>
  86. public string T_ItemName
  87. {
  88. get { return _t_ItemName; }
  89. set { _t_ItemName = value; }
  90. }
  91.  
  92. /// <summary>
  93. /// 项目数值
  94. /// </summary>
  95. private string _t_ItemValue = "";
  96.  
  97. /// <summary>
  98. /// 获取--设置--项目数值
  99. /// </summary>
  100. public string T_ItemValue
  101. {
  102. get { return _t_ItemValue; }
  103. set { _t_ItemValue = value; }
  104. }
  105.  
  106. /// <summary>
  107. /// X轴刻度
  108. /// </summary>
  109. private string _t_XScale = "";
  110.  
  111. /// <summary>
  112. /// 获取--设置--X轴刻度
  113. /// </summary>
  114. public string T_XScale
  115. {
  116. get { return _t_XScale; }
  117. set { _t_XScale = value; }
  118. }
  119.  
  120. #endregion
  121.  
  122. #region 图表属性
  123.  
  124. /// <summary>
  125. /// 图表名称ID
  126. /// </summary>
  127. private string _name = "";
  128.  
  129. /// <summary>
  130. /// 获取--设置--图表名称ID
  131. /// </summary>
  132. public string Name
  133. {
  134. get { return _name; }
  135. set { _name = value; }
  136. }
  137.  
  138. /// <summary>
  139. /// 图表类型
  140. /// </summary>
  141. private EChartType _chartType = EChartType.Curve;
  142.  
  143. /// <summary>
  144. /// 获取--设置--图表类型
  145. /// 默认:Line 折曲线
  146. /// </summary>
  147. public EChartType ChartType
  148. {
  149. get { return _chartType; }
  150. set { _chartType = value; }
  151. }
  152.  
  153. /// <summary>
  154. /// 图表宽度
  155. /// </summary>
  156. private int _chartWidth = ;
  157.  
  158. /// <summary>
  159. /// 获取--设置--图表宽度
  160. /// </summary>
  161. public int ChartWidth
  162. {
  163. get { return _chartWidth; }
  164. set { _chartWidth = value; }
  165. }
  166.  
  167. /// <summary>
  168. /// 图表高度
  169. /// </summary>
  170. private int _chartHeight = ;
  171.  
  172. /// <summary>
  173. /// 获取--设置--图表高度
  174. /// </summary>
  175. public int ChartHeight
  176. {
  177. get { return _chartHeight; }
  178. set { _chartHeight = value; }
  179. }
  180.  
  181. /// <summary>
  182. /// 图表背景颜色
  183. /// </summary>
  184. private Color _backColor = Color.White;
  185.  
  186. /// <summary>
  187. /// 获取--设置--图表背景颜色
  188. /// </summary>
  189. public Color BackColor
  190. {
  191. get { return _backColor; }
  192. set { _backColor = value; }
  193. }
  194.  
  195. /// <summary>
  196. /// 是否显示图表边框
  197. /// </summary>
  198. private bool _showBorder = true;
  199.  
  200. /// <summary>
  201. /// 获取--设置--是否显示图表边框
  202. /// 默认:true 显示
  203. /// </summary>
  204. public bool ShowBorder
  205. {
  206. get { return _showBorder; }
  207. set { _showBorder = value; }
  208. }
  209.  
  210. /// <summary>
  211. /// 图表边框颜色
  212. /// </summary>
  213. private Color _borderColor = Color.LightGray;
  214.  
  215. /// <summary>
  216. /// 获取--设置--图表边框颜色
  217. /// </summary>
  218. public Color BorderColor
  219. {
  220. get { return _borderColor; }
  221. set { _borderColor = value; }
  222. }
  223.  
  224. /// <summary>
  225. /// 是否显示网格线
  226. /// </summary>
  227. private bool _showGrid = true;
  228.  
  229. /// <summary>
  230. /// 获取--设置--是否显示网格线
  231. /// 默认:true 显示
  232. /// </summary>
  233. public bool ShowGrid
  234. {
  235. get { return _showGrid; }
  236. set { _showGrid = value; }
  237. }
  238.  
  239. /// <summary>
  240. /// 线条张力系数
  241. /// </summary>
  242. private float _lineTension = 0.3f;
  243.  
  244. /// <summary>
  245. /// 获取--设置--线条张力系数
  246. /// 默认:0.3
  247. /// </summary>
  248. public float LineTension
  249. {
  250. get { return _lineTension; }
  251. set
  252. {
  253. if (value < 0.0f && value > 1.0f)
  254. _lineTension = 0.5f;
  255. else
  256. _lineTension = value;
  257. }
  258. }
  259.  
  260. #endregion
  261.  
  262. #region 标题属性
  263.  
  264. /// <summary>
  265. /// 是否显示主标题
  266. /// </summary>
  267. private bool _showTitle = true;
  268.  
  269. /// <summary>
  270. /// 获取--设置--是否显示主标题
  271. /// 默认:true 显示
  272. /// </summary>
  273. public bool ShowTitle
  274. {
  275. get { return _showTitle; }
  276. set { _showTitle = value; }
  277. }
  278.  
  279. /// <summary>
  280. /// 主标题文本
  281. /// </summary>
  282. private string _title = "";
  283.  
  284. /// <summary>
  285. /// 获取--设置--主标题文本
  286. /// </summary>
  287. public string Title
  288. {
  289. get { return _title; }
  290. set { _title = value; }
  291. }
  292.  
  293. /// <summary>
  294. /// 主标题字体
  295. /// </summary>
  296. private Font _titleFont = new Font("黑体", );
  297.  
  298. /// <summary>
  299. /// 获取--设置--主标题字体
  300. /// </summary>
  301. public Font TitleFont
  302. {
  303. get { return _titleFont; }
  304. set { _titleFont = value; }
  305. }
  306.  
  307. /// <summary>
  308. /// 主标题颜色
  309. /// </summary>
  310. private Color _titleColor = Color.Black;
  311.  
  312. /// <summary>
  313. /// 获取--设置--主标题颜色
  314. /// </summary>
  315. public Color TitleColor
  316. {
  317. get { return _titleColor; }
  318. set { _titleColor = value; }
  319. }
  320.  
  321. /// <summary>
  322. /// 主标题对齐方式
  323. /// </summary>
  324. private EAlign _titleAlign = EAlign.center;
  325.  
  326. /// <summary>
  327. /// 获取--设置--主标题对齐方式
  328. /// </summary>
  329. public EAlign TitleAlign
  330. {
  331. get { return _titleAlign; }
  332. set { _titleAlign = value; }
  333. }
  334.  
  335. /// <summary>
  336. /// 是否显示副标题
  337. /// </summary>
  338. private bool _showSubTilte = true;
  339.  
  340. /// <summary>
  341. /// 获取--设置--是否显示副标题
  342. /// 默认:true 显示
  343. /// </summary>
  344. public bool ShowSubTitle
  345. {
  346. get { return _showSubTilte; }
  347. set { _showSubTilte = value; }
  348. }
  349.  
  350. /// <summary>
  351. /// 副标题文本
  352. /// </summary>
  353. private string _subTitle = "";
  354.  
  355. /// <summary>
  356. /// 获取--设置--副标题文本
  357. /// </summary>
  358. public string SubTitle
  359. {
  360. get { return _subTitle; }
  361. set { _subTitle = value; }
  362. }
  363.  
  364. /// <summary>
  365. /// 副标题字体
  366. /// </summary>
  367. private Font _subTitleFont = new Font("黑体", );
  368.  
  369. /// <summary>
  370. /// 获取--设置--副标题字体
  371. /// </summary>
  372. public Font SubTitleFont
  373. {
  374. get { return _subTitleFont; }
  375. set { _subTitleFont = value; }
  376. }
  377.  
  378. /// <summary>
  379. /// 副标题颜色
  380. /// </summary>
  381. private Color _subTitleColor = Color.Blue;
  382.  
  383. /// <summary>
  384. /// 获取--设置--副标题颜色
  385. /// </summary>
  386. public Color SubTitleColor
  387. {
  388. get { return _subTitleColor; }
  389. set { _subTitleColor = value; }
  390. }
  391.  
  392. /// <summary>
  393. /// 副标题对齐方式
  394. /// </summary>
  395. private EAlign _subTitleAlign = EAlign.center;
  396.  
  397. /// <summary>
  398. /// 获取--设置--副标题对齐方式
  399. /// </summary>
  400. public EAlign SubTitleAlign
  401. {
  402. get { return _subTitleAlign; }
  403. set { _subTitleAlign = value; }
  404. }
  405.  
  406. /// <summary>
  407. /// 副标题水平方向偏移量
  408. /// + - 整数
  409. /// </summary>
  410. private int _subTitleOffset = ;
  411.  
  412. /// <summary>
  413. /// 获取--设置--副标题水平方向偏移量
  414. /// </summary>
  415. public int SubTitleOffset
  416. {
  417. get { return _subTitleOffset; }
  418. set { _subTitleOffset = value; }
  419. }
  420.  
  421. #endregion
  422.  
  423. #region 图例属性
  424.  
  425. /// <summary>
  426. /// 是否显示图例
  427. /// </summary>
  428. private bool _showLegend = true;
  429.  
  430. /// <summary>
  431. /// 是否显示图例
  432. /// </summary>
  433. public bool ShowLegend
  434. {
  435. get { return _showLegend; }
  436. set { _showLegend = value; }
  437. }
  438.  
  439. /// <summary>
  440. /// 图例字体
  441. /// </summary>
  442. private Font _legendFont = new Font("宋体", );
  443.  
  444. /// <summary>
  445. /// 获取--设置--图例字体
  446. /// </summary>
  447. public Font LegendFont
  448. {
  449. get { return _legendFont; }
  450. set { _legendFont = value; }
  451. }
  452.  
  453. /// <summary>
  454. /// 图例字体颜色
  455. /// </summary>
  456. private Color _legendColor = Color.Black;
  457.  
  458. /// <summary>
  459. /// 获取--设置--图例字体颜色
  460. /// </summary>
  461. public Color LegendColor
  462. {
  463. get { return _legendColor; }
  464. set { _legendColor = value; }
  465. }
  466.  
  467. /// <summary>
  468. /// 图例对齐方式
  469. /// </summary>
  470. private EAlign _legendAlign = EAlign.center;
  471.  
  472. /// <summary>
  473. /// 获取--设置--图例对齐方式
  474. /// </summary>
  475. public EAlign LegendAlign
  476. {
  477. get { return _legendAlign; }
  478. set { _legendAlign = value; }
  479. }
  480.  
  481. #endregion
  482.  
  483. #region 坐标属性
  484.  
  485. /// <summary>
  486. /// 获取--X轴分割段数
  487. /// </summary>
  488. public int XSplitNum
  489. {
  490. get { return _xScaleValues.Count; }
  491. }
  492.  
  493. /// <summary>
  494. /// Y轴分割段数
  495. /// </summary>
  496. private int _ySplitNum = ;
  497.  
  498. /// <summary>
  499. /// 获取--设置--分割段数
  500. /// 默认:5
  501. /// 范围:最小5
  502. /// </summary>
  503. public int YSplitNum
  504. {
  505. get { return _ySplitNum; }
  506. set
  507. {
  508. if (value < )
  509. _ySplitNum = ;
  510. else
  511. _ySplitNum = value;
  512.  
  513. }
  514. }
  515.  
  516. /// <summary>
  517. /// X 轴标
  518. /// </summary>
  519. private string _xAxisText = "";
  520.  
  521. /// <summary>
  522. /// 获取--设置--X 轴标
  523. /// </summary>
  524. public string XAxisText
  525. {
  526. get { return _xAxisText; }
  527. set { _xAxisText = value; }
  528. }
  529.  
  530. /// <summary>
  531. /// Y 轴标
  532. /// </summary>
  533. private string _yAxisText = "";
  534.  
  535. /// <summary>
  536. /// 获取--设置--Y 轴标
  537. /// </summary>
  538. public string YAxisText
  539. {
  540. get { return _yAxisText; }
  541. set { _yAxisText = value; }
  542. }
  543.  
  544. /// <summary>
  545. /// X轴文本旋转角度
  546. /// 默认:0
  547. /// 范围:0~90
  548. /// </summary>
  549. private float _xRotateAngle = 0.0f;
  550.  
  551. /// <summary>
  552. /// 获取--设置--X轴文本旋转角度
  553. /// </summary>
  554. public float XRotateAngle
  555. {
  556. get { return _xRotateAngle; }
  557. set
  558. {
  559. if (value >= 0.0f && value <= 90.0f)
  560. _xRotateAngle = value;
  561. else
  562. _xRotateAngle = 0.0f;
  563. }
  564. }
  565.  
  566. #endregion
  567.  
  568. #region 绘图变量
  569.  
  570. /// <summary>
  571. /// 绘图对象
  572. /// </summary>
  573. private Graphics g = null;
  574.  
  575. /// <summary>
  576. /// 图表颜色数组
  577. /// </summary>
  578. private static Color[] ChartColor = {
  579. Color.Red, Color.Blue, Color.Orange, Color.Green, Color.Cyan, Color.Purple,
  580. Color.Coral, Color.Chocolate, Color.Gray, Color.Gold, Color.Lavender, Color.Linen,
  581. Color.Magenta, Color.Moccasin, Color.Navy, Color.Olive, Color.Peru, Color.Plum,
  582. Color.Purple, Color.Salmon, Color.Sienna, Color.Silver, Color.Tan, Color.Tomato,
  583. Color.Violet, Color.Turquoise, Color.Transparent
  584. };
  585.  
  586. /// <summary>
  587. /// 边距10px
  588. /// </summary>
  589. private float Margin = ;
  590.  
  591. /// <summary>
  592. /// 起点 X 坐标
  593. /// </summary>
  594. private float Start_X = ;
  595.  
  596. /// <summary>
  597. /// 起点 Y 坐标
  598. /// </summary>
  599. private float Start_Y = ;
  600.  
  601. /// <summary>
  602. /// 终点 X 坐标
  603. /// </summary>
  604. private float End_X = ;
  605.  
  606. /// <summary>
  607. /// 终点 Y 坐标
  608. /// </summary>
  609. private float End_Y = ;
  610.  
  611. /// <summary>
  612. /// X轴刻度宽度
  613. /// </summary>
  614. private float XScaleWidth = ;
  615.  
  616. /// <summary>
  617. /// Y轴刻度宽度
  618. /// </summary>
  619. private float YScaleWidth = ;
  620.  
  621. /// <summary>
  622. /// Y轴刻度间隔值
  623. /// 说明:Y轴坐标全部采用整数,表示每个间隔的计算单位值
  624. /// 包含正负数
  625. /// </summary>
  626. private double YScale_SplitValue = ;
  627.  
  628. /// <summary>
  629. /// Y轴刻度开始值
  630. /// </summary>
  631. private double YScale_StartValue = ;
  632.  
  633. /// <summary>
  634. /// 坐标轴原点坐标
  635. /// </summary>
  636. private PointF AxisZeroPt = new PointF(0f, 0f);
  637.  
  638. /// <summary>
  639. /// 图表数据
  640. /// </summary>
  641. private string _chartData = "";
  642.  
  643. /// <summary>
  644. /// 获取--设置--图表数据
  645. /// </summary>
  646. public string ChartData
  647. {
  648. get { return _chartData; }
  649. set { _chartData = value; }
  650. }
  651.  
  652. /// <summary>
  653. /// 绘图笔刷
  654. /// </summary>
  655. private Brush brush;
  656.  
  657. /// <summary>
  658. /// 绘制画笔
  659. /// </summary>
  660. private Pen pen;
  661.  
  662. /// <summary>
  663. /// 绘图矩形
  664. /// </summary>
  665. private RectangleF rectF = new RectangleF(, , , );
  666.  
  667. /// <summary>
  668. /// 字符格式化
  669. /// </summary>
  670. private StringFormat stringFormat;
  671.  
  672. /// <summary>
  673. /// 临时变量 最大值
  674. /// </summary>
  675. private double myMaxValue = ;
  676.  
  677. /// <summary>
  678. /// 临时变量 最小值
  679. /// </summary>
  680. private double myMinValue = ;
  681.  
  682. /// <summary>
  683. /// 临时变量 X轴刻度最大高度
  684. /// 用于绘制坐标轴的时候进行偏移
  685. /// </summary>
  686. private float myXScaleMaxHeight = ;
  687.  
  688. /// <summary>
  689. /// 临时变量 Y轴刻度值字符串的最大宽度
  690. /// 用于绘制坐标轴的时候进行偏移
  691. /// </summary>
  692. private float myYScaleMaxWidth = ;
  693.  
  694. #endregion
  695.  
  696. #region 图表数据
  697.  
  698. /// <summary>
  699. /// X轴刻度值数组
  700. /// </summary>
  701. private List<string> _xScaleValues = new List<string>();
  702.  
  703. /// <summary>
  704. /// 获取--设置--X轴刻度值数组
  705. /// </summary>
  706. public List<string> XScaleValues
  707. {
  708. get { return _xScaleValues; }
  709. set { _xScaleValues = value; }
  710. }
  711.  
  712. /// <summary>
  713. /// 图表数据
  714. /// </summary>
  715. private List<EChartData> _chartDataArray = new List<EChartData>();
  716.  
  717. /// <summary>
  718. /// 获取--设置--图表数据
  719. /// </summary>
  720. public List<EChartData> ChartDataArray
  721. {
  722. get { return _chartDataArray; }
  723. set { _chartDataArray = value; }
  724. }
  725.  
  726. #endregion
  727.  
  728. #endregion
  729.  
  730. #region 构造方法
  731.  
  732. /// <summary>
  733. /// 构造函数
  734. /// </summary>
  735. public EChart()
  736. {
  737.  
  738. }
  739.  
  740. /// <summary>
  741. /// 构造函数
  742. /// </summary>
  743. /// <param name="eChart"></param>
  744. public EChart(EChart eChart)
  745. {
  746.  
  747. }
  748.  
  749. #endregion
  750.  
  751. #region 生成图表
  752.  
  753. /// <summary>
  754. /// 生成图表
  755. /// </summary>
  756. /// <returns>返回:图表图像</returns>
  757. public Bitmap CreateImage()
  758. {
  759. Bitmap ChartImage = new Bitmap(ChartWidth, ChartHeight);
  760. g = Graphics.FromImage(ChartImage);
  761. g.SmoothingMode = SmoothingMode.Default;
  762. g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
  763. g.Clear(Color.White);
  764.  
  765. Start_X = Margin;
  766. Start_Y = Margin;
  767. End_X = ChartWidth - Margin;
  768. End_Y = ChartHeight - Margin;
  769.  
  770. DrawChart();
  771.  
  772. g.Dispose();
  773.  
  774. return ChartImage;
  775. }
  776.  
  777. #endregion
  778.  
  779. #region 绘制方法
  780.  
  781. /// <summary>
  782. /// 绘制图表
  783. /// </summary>
  784. private void DrawChart()
  785. {
  786. DrawChart_InitGraph();
  787. DrawChart_MainTitle();
  788. DrawChart_SubTitle();
  789. DrawChart_Legend();
  790. DrawChart_YAxisText();
  791. if (ChartType != EChartType.Pie)
  792. {
  793. DrawChart_Axis();
  794. if (ChartType == EChartType.Curve)
  795. DrawChart_Curve();
  796. else
  797. DrawChart_Bar();
  798. }
  799. else
  800. {
  801. DrawChart_Pie();
  802. }
  803. }
  804.  
  805. /// <summary>
  806. /// 绘制图表--绘制背景图
  807. /// </summary>
  808. private void DrawChart_InitGraph()
  809. {
  810. // 绘制图表外围边框
  811. if (_showBorder)
  812. g.DrawRectangle(new Pen(BorderColor, ), , , (ChartWidth - ), (ChartHeight - ));
  813.  
  814. // 填充图表背景颜色
  815. g.FillRectangle(new SolidBrush(BackColor), , , ChartWidth - , ChartHeight - );
  816.  
  817. }
  818.  
  819. /// <summary>
  820. /// 绘制图表--绘制主标题
  821. /// </summary>
  822. private void DrawChart_MainTitle()
  823. {
  824. if (ShowTitle)
  825. {
  826. if (Title != null && Title.Trim() != "")
  827. {
  828. brush = new SolidBrush(TitleColor); // 矩形填充笔刷
  829. SizeF sizeF = g.MeasureString(Title, TitleFont); // 测试字体大小
  830. stringFormat = new StringFormat(); // 格式化字符串
  831. stringFormat.LineAlignment = StringAlignment.Center; // 垂直对齐方式
  832. switch (TitleAlign) // 水平对齐方式
  833. {
  834. case EAlign.center:
  835. stringFormat.Alignment = StringAlignment.Center;
  836. break;
  837. case EAlign.right:
  838. stringFormat.Alignment = StringAlignment.Far;
  839. break;
  840. default:
  841. stringFormat.Alignment = StringAlignment.Near;
  842. break;
  843. }
  844.  
  845. rectF = new RectangleF(Start_X, Start_Y, (float)(ChartWidth - ), sizeF.Height); // 文字的矩形
  846. g.DrawString(Title, TitleFont, brush, rectF, stringFormat); // 绘制主标题
  847. Start_Y += sizeF.Height + 3f; // 设置Y起点值 + 3px
  848. }
  849. }
  850. }
  851.  
  852. /// <summary>
  853. /// 绘制图表--绘制副标题
  854. /// </summary>
  855. private void DrawChart_SubTitle()
  856. {
  857. if (ShowSubTitle)
  858. {
  859. if (SubTitle != null && SubTitle.Trim() != "")
  860. {
  861. brush = new SolidBrush(SubTitleColor); // 矩形填充笔刷
  862. SizeF sizeF = g.MeasureString(SubTitle, SubTitleFont); // 测试字体大小
  863. stringFormat = new StringFormat(); // 格式化字符串
  864. stringFormat.LineAlignment = StringAlignment.Center; // 垂直对齐方式
  865. switch (SubTitleAlign) // 水平对齐方式
  866. {
  867. case EAlign.center:
  868. stringFormat.Alignment = StringAlignment.Center;
  869. break;
  870. case EAlign.right:
  871. stringFormat.Alignment = StringAlignment.Far;
  872. break;
  873. default:
  874. stringFormat.Alignment = StringAlignment.Near;
  875. break;
  876. }
  877.  
  878. rectF = new RectangleF(Start_X + (float)SubTitleOffset, Start_Y, (float)(ChartWidth - ), sizeF.Height); // 文字的矩形
  879. g.DrawString(SubTitle, SubTitleFont, brush, rectF, stringFormat); // 绘制副标题
  880.  
  881. Start_Y += sizeF.Height + 3f; // 设置Y起点值 + 3px
  882. }
  883. }
  884.  
  885. }
  886.  
  887. /// <summary>
  888. /// 绘制图表--绘制图例
  889. /// </summary>
  890. private void DrawChart_Legend()
  891. {
  892. // 计算项目颜色
  893. int tmIndex = ;
  894. for (int m = ; m < ChartDataArray.Count; m++)
  895. {
  896. tmIndex = m % ChartColor.Length;
  897. ChartDataArray[m].ItemColor = ChartColor[tmIndex];
  898. }
  899.  
  900. // 图例的高度最大40px 3排
  901. if (ShowLegend)
  902. {
  903. // 计算文字大小
  904. int LegendCount = ChartDataArray.Count;
  905. Font tFont = new Font("宋体", );
  906. for (int t = ; t < LegendCount; t++)
  907. {
  908. SizeF tmSize = new SizeF();
  909. tmSize = g.MeasureString(ChartDataArray[t].Name, tFont);
  910. ChartDataArray[t].NameSize = tmSize;
  911. }
  912.  
  913. #region 绘制一排图例
  914.  
  915. // 首先判定一行够不够
  916. float largMax = ;
  917. for (int t = ; t < LegendCount; t++)
  918. {
  919. if (t == )
  920. largMax += ChartDataArray[t].NameSize.Width;
  921. else
  922. largMax += (35f + ChartDataArray[t].NameSize.Width);
  923. }
  924.  
  925. if (largMax <= End_X - Start_X) // 图例只需一排
  926. {
  927. End_Y -= 12.0f;
  928. float tmX = (End_X - Start_X - largMax) / + Start_X;
  929. float tmY = End_Y;
  930. for (int n = ; n < LegendCount; n++)
  931. {
  932. g.FillRectangle(new SolidBrush(ChartDataArray[n].ItemColor), tmX, tmY + , , );
  933. tmX += ;
  934. g.DrawString(ChartDataArray[n].Name, new Font("宋体", ), new SolidBrush(Color.Black), tmX, tmY);
  935. tmX += + ChartDataArray[n].NameSize.Width;
  936. }
  937. }
  938.  
  939. #endregion
  940.  
  941. #region 绘制多排图例
  942.  
  943. // 图例最多绘制三排
  944. else
  945. {
  946.  
  947. bool TwoLine = true; // 是否两行:true 是; false: 否,为三行
  948.  
  949. // 判定两排还是三排
  950. float tmBX = Start_X - ;
  951. int tmBC = (int)Math.Ceiling((double)LegendCount / );
  952. for (int T = ; T < tmBC; T++)
  953. {
  954. float tmBW1 = -1F, tmBW2 = -1F, tmBM = 0F;
  955. tmBW1 = ChartDataArray[T * ].NameSize.Width;
  956. if (ChartDataArray.Count > (T * + ))
  957. tmBW2 = ChartDataArray[T * + ].NameSize.Width;
  958. tmBM = tmBW1 > tmBW2 ? tmBW1 : tmBW2;
  959. tmBX += + tmBM;
  960. if (tmBX > (End_X + ))
  961. {
  962. TwoLine = false;
  963. break;
  964. }
  965. }
  966.  
  967. // 绘制两排图例
  968. if (TwoLine)
  969. {
  970. End_Y -= 24.0f;
  971. float tmTX = (End_X + - tmBX + Start_X + ) / ; // 开始位置保持两排水平居中
  972. float tmTY = End_Y;
  973. int tmTM = (int)Math.Ceiling((double)LegendCount / );
  974.  
  975. // 绘制两排图例
  976. for (int T = ; T < tmTM; T++)
  977. {
  978. float tmTW1 = -1F, tmTW2 = -1F, tmTW3 = 0F;
  979. tmTW1 = ChartDataArray[T * ].NameSize.Width;
  980. if (ChartDataArray.Count > (T * + ))
  981. tmTW2 = ChartDataArray[T * + ].NameSize.Width;
  982. tmTW3 = tmTW1 > tmTW2 ? tmTW1 : tmTW2;
  983.  
  984. // 绘制第一排图例
  985. g.FillRectangle(new SolidBrush(ChartDataArray[T * ].ItemColor), tmTX, tmTY + , , );
  986. g.DrawString(ChartDataArray[T * ].Name, new Font("宋体", ), new SolidBrush(Color.Black), (tmTX + ), tmTY);
  987.  
  988. // 绘制第二排图例
  989. if (tmTW2 > )
  990. {
  991. g.FillRectangle(new SolidBrush(ChartDataArray[T * + ].ItemColor), tmTX, (tmTY + + ), , );
  992. g.DrawString(ChartDataArray[T * + ].Name, new Font("宋体", ), new SolidBrush(Color.Black), (tmTX + ), (tmTY + ));
  993. }
  994. tmTX += + tmTW3;
  995. }
  996. }
  997.  
  998. // 绘制三排图例
  999. else
  1000. {
  1001. End_Y -= 40.0f;
  1002. // 如果三排还不够,那么就不管了,绘制超出范围就超出范围
  1003. float tmSX = Start_X - ;
  1004. float tmSY = End_Y;
  1005. int tmSC = (int)Math.Ceiling((double)LegendCount / );
  1006. bool CanFlag = true; // 三排是否足够
  1007.  
  1008. // 首先计算三排的能排下的居中位置
  1009. for (int n = ; n < tmSC; n++)
  1010. {
  1011. float tmSW1 = -1F, tmSW2 = -1F, tmSW3 = -1F, tmSW4 = 0F;
  1012. tmSW1 = ChartDataArray[n * ].NameSize.Width;
  1013. if (ChartDataArray.Count > (n * + ))
  1014. tmSW2 = ChartDataArray[n * + ].NameSize.Width;
  1015. if (ChartDataArray.Count > (n * + ))
  1016. tmSW3 = ChartDataArray[n * + ].NameSize.Width;
  1017. tmSW4 = tmSW1 > tmSW2 ? tmSW1 : tmSW2;
  1018. tmSW4 = tmSW4 > tmSW3 ? tmSW4 : tmSW3;
  1019. tmSX += + tmSW4;
  1020. if (tmSX > (End_X + ))
  1021. {
  1022. CanFlag = false;
  1023. break;
  1024. }
  1025. }
  1026.  
  1027. // 再次执行三排绘制
  1028. if (CanFlag) // 三排足够,则设置居中开始位置
  1029. tmSX = (End_X + - tmSX + Start_X + ) / ;
  1030. else
  1031. tmSX = Start_X - ; // 三排排不下的情况就从5px 开始
  1032.  
  1033. for (int n = ; n < tmSC; n++)
  1034. {
  1035. float tmSW1 = -1F, tmSW2 = -1F, tmSW3 = -1F, tmSW4 = 0F;
  1036. tmSW1 = ChartDataArray[n * ].NameSize.Width;
  1037. if (ChartDataArray.Count > (n * + ))
  1038. tmSW2 = ChartDataArray[n * + ].NameSize.Width;
  1039. if (ChartDataArray.Count > (n * + ))
  1040. tmSW3 = ChartDataArray[n * + ].NameSize.Width;
  1041. tmSW4 = tmSW1 > tmSW2 ? tmSW1 : tmSW2;
  1042. tmSW4 = tmSW4 > tmSW3 ? tmSW4 : tmSW3;
  1043.  
  1044. // 绘制第一排图例
  1045. g.FillRectangle(new SolidBrush(ChartDataArray[n * ].ItemColor), tmSX, (tmSY + ), , );
  1046. g.DrawString(ChartDataArray[n * ].Name, new Font("宋体", ), new SolidBrush(Color.Black), (tmSX + ), tmSY);
  1047.  
  1048. // 绘制第二排图例
  1049. if (tmSW2 > )
  1050. {
  1051. g.FillRectangle(new SolidBrush(ChartDataArray[n * + ].ItemColor), tmSX, (tmSY + + ), , );
  1052. g.DrawString(ChartDataArray[n * + ].Name, new Font("宋体", ), new SolidBrush(Color.Black), (tmSX + ), (tmSY + ));
  1053. }
  1054.  
  1055. // 绘制第三排图例
  1056. if (tmSW3 > )
  1057. {
  1058. g.FillRectangle(new SolidBrush(ChartDataArray[n * + ].ItemColor), tmSX, (tmSY + + ), , );
  1059. g.DrawString(ChartDataArray[n * + ].Name, new Font("宋体", ), new SolidBrush(Color.Black), (tmSX + ), (tmSY + ));
  1060. }
  1061.  
  1062. tmSX += + tmSW4;
  1063. }
  1064. }
  1065. }
  1066.  
  1067. #endregion
  1068. }
  1069. }
  1070.  
  1071. /// <summary>
  1072. /// 绘制图表--绘制X轴标
  1073. /// </summary>
  1074. /// <param name="g"></param>
  1075. private void DrawChart_XAxisText()
  1076. {
  1077. // X轴标就不绘制了,因为空间不够,所以不执行X轴标的绘制
  1078. }
  1079.  
  1080. /// <summary>
  1081. /// 绘制图表--绘制Y轴标
  1082. /// </summary>
  1083. private void DrawChart_YAxisText()
  1084. {
  1085. if (ChartType != EChartType.Pie)
  1086. {
  1087. if (YAxisText != null && YAxisText.Trim() != "")
  1088. {
  1089. brush = new SolidBrush(Color.Gray);
  1090. stringFormat = new StringFormat(); // 格式化字符串
  1091. stringFormat.LineAlignment = StringAlignment.Near; // 垂直对齐方式
  1092. stringFormat.Alignment = StringAlignment.Near; // 水平对齐方式
  1093. SizeF sizeF = g.MeasureString(YAxisText, new Font("宋体", )); // 测量文字大小
  1094. rectF = new RectangleF(Start_X, Start_Y, sizeF.Width, sizeF.Height); // 文字外围矩形
  1095. g.TranslateTransform((Start_X - Start_Y), (Start_X + Start_Y + sizeF.Width)); // 设置位置移动 X,Y
  1096. g.RotateTransform(); // 旋转270度 以左上角作为旋转原点
  1097. g.DrawString(YAxisText, new Font("宋体", ), brush, rectF, stringFormat);
  1098. g.ResetTransform();
  1099.  
  1100. Start_X += sizeF.Height + ; // 加2个像素
  1101. }
  1102. }
  1103. }
  1104.  
  1105. /// <summary>
  1106. /// 绘制图表--绘制坐标轴
  1107. /// </summary>
  1108. private void DrawChart_Axis()
  1109. {
  1110. // 1、图表区下移10PX
  1111. Start_Y += ;
  1112.  
  1113. // 2、计算坐标轴参数
  1114. Calc_XScaleHeight();
  1115. Calc_YScaleValue();
  1116.  
  1117. // 3、计算原点坐标值
  1118. AxisZeroPt = new PointF(0f, 0f); // 坐标轴原点坐标
  1119. AxisZeroPt.X = Start_X + myYScaleMaxWidth;
  1120. AxisZeroPt.Y = End_Y - myXScaleMaxHeight;
  1121.  
  1122. // 3.1、绘制坐标轴
  1123. Pen pen2 = new Pen(Color.FromKnownColor(KnownColor.ControlDark), 2f);
  1124. g.DrawLine(pen2, (Start_X + myYScaleMaxWidth - 4f), (End_Y - myXScaleMaxHeight), End_X + , (End_Y - myXScaleMaxHeight)); // 绘制 X坐标轴
  1125. g.DrawLine(pen2, (Start_X + myYScaleMaxWidth), (End_Y - myXScaleMaxHeight + 4f), (Start_X + myYScaleMaxWidth), Start_Y - ); // 绘制 Y坐标轴
  1126.  
  1127. // 3.2、计算分段宽
  1128. XScaleWidth = (End_X - Start_X - myYScaleMaxWidth) / XSplitNum; // 计算X轴分段宽
  1129. YScaleWidth = (End_Y - Start_Y - myXScaleMaxHeight) / YSplitNum; // 计算Y轴分段宽
  1130.  
  1131. // 3.3、绘制刻度值
  1132. pen = new Pen(Color.LightGray, 1f);
  1133. pen.DashStyle = DashStyle.Dash;
  1134. for (int k = ; k < XSplitNum; k++) // 绘制X轴刻度线 刻度值
  1135. {
  1136. // 绘制X轴刻度线
  1137. g.DrawLine(pen2, (AxisZeroPt.X + XScaleWidth * (k + )), AxisZeroPt.Y, (AxisZeroPt.X + XScaleWidth * (k + )), AxisZeroPt.Y + 4f);
  1138.  
  1139. // 绘制X轴刻度值
  1140. g.TranslateTransform(AxisZeroPt.X + XScaleWidth * k + 15f * XRotateAngle / + 4f, AxisZeroPt.Y + 4f); // 平移原点
  1141. g.RotateTransform(XRotateAngle, MatrixOrder.Prepend); // 旋转图像
  1142. g.DrawString(XScaleValues[k], new Font("宋体", 9f), new SolidBrush(Color.Black), , ); // 绘制字符
  1143. g.ResetTransform();
  1144. }
  1145.  
  1146. for (int k = ; k < YSplitNum; k++)
  1147. {
  1148. // 绘制Y轴刻度线
  1149. g.DrawLine(pen2, AxisZeroPt.X - , (AxisZeroPt.Y - YScaleWidth * (k + )), AxisZeroPt.X, (AxisZeroPt.Y - YScaleWidth * (k + )));
  1150.  
  1151. // 绘制Y轴刻度值
  1152. string tmYvalue = (YScale_StartValue + k * YScale_SplitValue).ToString();
  1153. SizeF tmF = g.MeasureString(tmYvalue, new Font("宋体", ));
  1154. g.DrawString(tmYvalue, new Font("宋体", ), new SolidBrush(Color.Black), (AxisZeroPt.X - tmF.Width - ), (AxisZeroPt.Y - YScaleWidth * k - tmF.Height / + ));
  1155.  
  1156. if (k == YSplitNum - )
  1157. {
  1158. tmYvalue = (YScale_StartValue + (k + ) * YScale_SplitValue).ToString();
  1159. tmF = g.MeasureString(tmYvalue, new Font("宋体", ));
  1160. g.DrawString(tmYvalue, new Font("宋体", ), new SolidBrush(Color.Black), (AxisZeroPt.X - tmF.Width - ), (AxisZeroPt.Y - YScaleWidth * (k + ) - tmF.Height / + ));
  1161. }
  1162. }
  1163.  
  1164. // 3.4、绘制网格线
  1165. if (ShowGrid)
  1166. {
  1167. for (int k = ; k <= YSplitNum; k++) // 绘制X轴平行横向辅助线
  1168. g.DrawLine(pen, AxisZeroPt.X + , (AxisZeroPt.Y - YScaleWidth * k), End_X, (AxisZeroPt.Y - YScaleWidth * k));
  1169.  
  1170. for (int k = ; k <= XSplitNum; k++) // 绘制Y轴平行纵向辅助线
  1171. g.DrawLine(pen, (AxisZeroPt.X + XScaleWidth * k), Start_Y, (AxisZeroPt.X + XScaleWidth * k), AxisZeroPt.Y - );
  1172. }
  1173.  
  1174. pen2.Dispose();
  1175. }
  1176.  
  1177. /// <summary>
  1178. /// 绘制曲线图
  1179. /// </summary>
  1180. private void DrawChart_Curve()
  1181. {
  1182. g.SmoothingMode = SmoothingMode.HighQuality;
  1183. g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
  1184. g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
  1185.  
  1186. int tmLength = ;
  1187. PointF[] CurvePointF = new PointF[tmLength];
  1188. foreach (EChartData iItem in this.ChartDataArray)
  1189. {
  1190. tmLength = iItem.Values.Count;
  1191. CurvePointF = new PointF[tmLength];
  1192. pen = new Pen(iItem.ItemColor, 2.0f);
  1193. for (int rr = ; rr < iItem.Values.Count; rr++)
  1194. {
  1195. double dbValue = iItem.Values[rr];
  1196. CurvePointF[rr].X = AxisZeroPt.X + XScaleWidth * rr + XScaleWidth / ;
  1197. CurvePointF[rr].Y = AxisZeroPt.Y - (float)((dbValue - YScale_StartValue) / YScale_SplitValue) * YScaleWidth;
  1198. }
  1199.  
  1200. // 绘制曲线
  1201. g.DrawCurve(pen, CurvePointF, LineTension);
  1202.  
  1203. // 绘制辅点
  1204. for (int tt = ; tt < CurvePointF.Length; tt++)
  1205. {
  1206. // 点标数据值
  1207. string tmValStr = iItem.Values[tt].ToString();
  1208.  
  1209. // 绘制数据点
  1210. g.FillEllipse(new SolidBrush(iItem.ItemColor), CurvePointF[tt].X - , CurvePointF[tt].Y - , , );
  1211.  
  1212. // 绘制数据值
  1213. SizeF tmValueSize = g.MeasureString(tmValStr, new Font("Arial", ));
  1214. g.DrawString(tmValStr, new Font("Arial", ), new SolidBrush(iItem.ItemColor), (CurvePointF[tt].X - tmValueSize.Width / ), (CurvePointF[tt].Y - tmValueSize.Height - 2f));
  1215. }
  1216. }
  1217. }
  1218.  
  1219. /// <summary>
  1220. /// 绘制柱状图
  1221. /// </summary>
  1222. private void DrawChart_Bar()
  1223. {
  1224. g.SmoothingMode = SmoothingMode.HighQuality;
  1225. int tmLen = ChartDataArray.Count; // 柱形条目总数
  1226. float tmBarWidth = XScaleWidth / (tmLen * + ); // 每条柱形宽度 平均分配
  1227. if (tmBarWidth < )
  1228. {
  1229. tmBarWidth = 2f;
  1230. }
  1231.  
  1232. for (int kk = ; kk < this.ChartDataArray.Count; kk++)
  1233. {
  1234. EChartData iItem = this.ChartDataArray[kk];
  1235. pen = new Pen(Color.FromKnownColor(KnownColor.ControlDark), 1.0f);
  1236. for (int rr = ; rr < iItem.Values.Count; rr++)
  1237. {
  1238. RectangleF barRect = new RectangleF(, , , );
  1239. double dbValue = iItem.Values[rr];
  1240. barRect.X = AxisZeroPt.X + XScaleWidth * rr + (tmBarWidth * ((kk + ) * - ));
  1241. barRect.Y = AxisZeroPt.Y - (float)((dbValue - YScale_StartValue) / YScale_SplitValue) * YScaleWidth;
  1242. barRect.Width = tmBarWidth;
  1243. barRect.Height = AxisZeroPt.Y - barRect.Y;
  1244.  
  1245. // 绘制柱形
  1246. g.DrawRectangle(pen, barRect.X, barRect.Y, barRect.Width, barRect.Height);
  1247.  
  1248. brush = new SolidBrush(iItem.ItemColor);
  1249. g.FillRectangle(brush, barRect.X + , barRect.Y + , barRect.Width - , barRect.Height - );
  1250.  
  1251. // 绘制数据
  1252. SizeF tmValueSize = g.MeasureString(dbValue.ToString(), new Font("Arial", ));
  1253. g.DrawString(dbValue.ToString(), new Font("Arial", ), new SolidBrush(iItem.ItemColor), (barRect.X + tmBarWidth / - tmValueSize.Width / ), (barRect.Y - tmValueSize.Height - 2f));
  1254. }
  1255. }
  1256. }
  1257.  
  1258. /// <summary>
  1259. /// 绘制图表--绘制饼状图
  1260. /// </summary>
  1261. private void DrawChart_Pie()
  1262. {
  1263. // 上下预留20 PX 为了标记饼图的数据值
  1264. Start_Y += ;
  1265. End_Y -= ;
  1266.  
  1267. g.SmoothingMode = SmoothingMode.HighQuality;
  1268. g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
  1269. g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
  1270.  
  1271. // 矩形坐标点
  1272. PointF piePoint = new PointF(, );
  1273. float tmPieW = End_X - Start_X;
  1274. float tmPieH = End_Y - Start_Y;
  1275. float tmPieR = tmPieW < tmPieH ? tmPieW / : tmPieH / ; // 半径
  1276.  
  1277. piePoint.X = Start_X + tmPieW / - tmPieR;
  1278. piePoint.Y = Start_Y + tmPieH / - tmPieR;
  1279.  
  1280. // 圆心坐标点
  1281. PointF pieZero = new PointF(piePoint.X + tmPieR, piePoint.Y + tmPieR);
  1282.  
  1283. // 绘制外围圆
  1284. pen = new Pen(Color.FromKnownColor(KnownColor.ControlDark), 1.5f);
  1285. g.DrawEllipse(pen, piePoint.X - , piePoint.Y - , (tmPieR + ) * , (tmPieR + ) * );
  1286.  
  1287. // 计算总数
  1288. double pieCountValue = ;
  1289. foreach (EChartData iItem in this.ChartDataArray)
  1290. {
  1291. if (iItem.Values.Count >= )
  1292. pieCountValue += iItem.Values[];
  1293. }
  1294.  
  1295. // 绘制扇形
  1296. if (pieCountValue > )
  1297. {
  1298. float curAngle = ; // 占比角度
  1299. float sumAngle = ; // 总角度和
  1300.  
  1301. foreach (EChartData iItem in this.ChartDataArray)
  1302. {
  1303. if (iItem.Values.Count >= )
  1304. curAngle = (float)(iItem.Values[] / pieCountValue * );
  1305. else
  1306. curAngle = ;
  1307.  
  1308. // 填充笔刷
  1309. brush = new SolidBrush(iItem.ItemColor);
  1310.  
  1311. // 绘制弧形
  1312. g.FillPie(brush, piePoint.X, piePoint.Y, tmPieR * , tmPieR * , sumAngle, curAngle);
  1313.  
  1314. // 绘制弧线
  1315. g.DrawPie(pen, piePoint.X, piePoint.Y, tmPieR * , tmPieR * , sumAngle, curAngle);
  1316.  
  1317. // 绘制数据
  1318. float tmPre = (float)Math.Round((iItem.Values[] / pieCountValue) * , );
  1319. string tmStr = tmPre.ToString() + "%" + " [" + iItem.Values[].ToString() + "]";
  1320.  
  1321. // 内圆信息
  1322. double relCur_X = tmPieR * Math.Cos(( - sumAngle - curAngle / ) * Math.PI / );
  1323. double relCur_Y = tmPieR * Math.Sin(( - sumAngle - curAngle / ) * Math.PI / );
  1324. double cur_X = relCur_X + pieZero.X;
  1325. double cur_Y = pieZero.Y - relCur_Y;
  1326. PointF cur_Point = new PointF((float)cur_X, (float)cur_Y); // 内圆上弧线中间点的坐标
  1327.  
  1328. // 外圆信息
  1329. float largerR = tmPieR + ;
  1330. double relLarg_X = largerR * Math.Cos(( - sumAngle - curAngle / ) * Math.PI / );
  1331. double relLarg_Y = largerR * Math.Sin(( - sumAngle - curAngle / ) * Math.PI / );
  1332. double largerX = relLarg_X + pieZero.X;
  1333. double largerY = pieZero.Y - relLarg_Y;
  1334. PointF larger_Point = new PointF((float)largerX, (float)largerY);
  1335.  
  1336. SizeF calcSize = new SizeF(, );
  1337.  
  1338. // 绘制链接斜线(内圆到外圆弧度中间点的连接线)
  1339. g.DrawLine(new Pen(new SolidBrush(iItem.ItemColor), 1.5f), cur_Point, larger_Point); // 斜线
  1340.  
  1341. // 绘制横向线条
  1342. //*以下是对四个象限、以及对90度、180度、270度和360度的判断*//
  1343. float tmCurIf = sumAngle + curAngle / ;
  1344. if (tmCurIf <= )
  1345. {
  1346. g.DrawLine(new Pen(new SolidBrush(iItem.ItemColor), 1.5f), larger_Point.X, larger_Point.Y, larger_Point.X + 15f, larger_Point.Y); // 横线
  1347. g.DrawString(tmStr, new Font("Arial", ), new SolidBrush(iItem.ItemColor), larger_Point.X + 15f, larger_Point.Y - 8f); // 文字
  1348. }
  1349. else if (tmCurIf > && tmCurIf <= )
  1350. {
  1351. calcSize = g.MeasureString(tmStr, new Font("Arial", ));
  1352. g.DrawLine(new Pen(new SolidBrush(iItem.ItemColor), 1.5f), larger_Point.X, larger_Point.Y, larger_Point.X - 15f, larger_Point.Y); // 横线
  1353. g.DrawString(tmStr, new Font("Arial", ), new SolidBrush(iItem.ItemColor), larger_Point.X - 15f - calcSize.Width, larger_Point.Y - 8f); // 文字
  1354. }
  1355. else if (tmCurIf > && tmCurIf <= )
  1356. {
  1357. calcSize = g.MeasureString(tmStr, new Font("Arial", ));
  1358. g.DrawLine(new Pen(new SolidBrush(iItem.ItemColor), 1.5f), larger_Point.X, larger_Point.Y, larger_Point.X - 15f, larger_Point.Y); // 横线
  1359. g.DrawString(tmStr, new Font("Arial", ), new SolidBrush(iItem.ItemColor), larger_Point.X - 15f - calcSize.Width, larger_Point.Y - 8f); // 文字
  1360. }
  1361. else
  1362. {
  1363. g.DrawLine(new Pen(new SolidBrush(iItem.ItemColor), 1.5f), larger_Point.X, larger_Point.Y, larger_Point.X + 15f, larger_Point.Y); // 横线
  1364. g.DrawString(tmStr, new Font("Arial", ), new SolidBrush(iItem.ItemColor), larger_Point.X + 15f, larger_Point.Y - 8f); // 文字
  1365. }
  1366.  
  1367. ////*以下是对四个象限、以及对90度、180度、270度和360度的判断*//
  1368. //if ((sumAngle + curAngle / 2) < 90)
  1369. //{
  1370. // Half = sumAngle + curAngle / 2;
  1371. // double tem_sin = Math.Sin(Pi / 180 * Half);
  1372. // double tem_cos = Math.Cos(Pi / 180 * Half);
  1373.  
  1374. // //Math.PI
  1375.  
  1376. // float Px = (float)(tmPieR * tem_cos);
  1377. // float Py = (float)(tmPieR * tem_sin);
  1378.  
  1379. // g.DrawString(tmStr, new Font("Arial", 9), new SolidBrush(Color.Black), piePoint.X + tmPieR + Px, piePoint.Y + Py);
  1380. // //g.DrawString(arraylist_type[i].ToString(), font1, brush1, new Point(225 + x, 225 + y));
  1381. // //g.DrawString((Convert.ToInt32(arraylist_tp[i])).ToString() + "%", font1, brush1, new Point(225 + x, 225 + y + 12));
  1382. //}
  1383.  
  1384. //else if (tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 == 90)
  1385. //{
  1386. // g.DrawString(arraylist_type[i].ToString(), font1, brush1, new Point(225, 225 + 125));
  1387. // g.DrawString((Convert.ToInt32(arraylist_tp[i])).ToString() + "%", font1, brush1, new Point(225, 225 + 125 + 12));
  1388. //}
  1389.  
  1390. //else if (tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 > 90 && tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 < 180)
  1391. //{
  1392. // halfangle = (180 - tem_angle - Convert.ToSingle(arraylist_angle[i]) / 2);
  1393. // double tem_sin = Math.Sin(T / 180 * halfangle);
  1394. // double tem_cos = Math.Cos(T / 180 * halfangle);
  1395.  
  1396. // int y = Convert.ToInt32(125 * tem_sin);
  1397. // int x = Convert.ToInt32(125 * tem_cos);
  1398. // g.DrawString(arraylist_type[i].ToString(), font1, brush1, new Point(225 - x, 225 + y));
  1399. // g.DrawString((Convert.ToInt32(arraylist_tp[i])).ToString() + "%", font1, brush1, new Point(225 - x, 225 + y + 12));
  1400. //}
  1401.  
  1402. //else if (tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 == 180)
  1403. //{
  1404. // g.DrawString(arraylist_type[i].ToString(), font1, brush1, new Point(225 - 125, 225));
  1405. // g.DrawString((Convert.ToInt32(arraylist_tp[i])).ToString() + "%", font1, brush1, new Point(225 - 125, 225 + 12));
  1406. //}
  1407.  
  1408. //else if (tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 > 180 && tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 < 270)
  1409. //{
  1410. // halfangle = (tem_angle - 180 + Convert.ToSingle(arraylist_angle[i]) / 2);
  1411. // double tem_sin = Math.Sin(T / 180 * halfangle);
  1412. // double tem_cos = Math.Cos(T / 180 * halfangle);
  1413.  
  1414. // int y = Convert.ToInt32(125 * tem_sin);
  1415. // int x = Convert.ToInt32(125 * tem_cos);
  1416. // g.DrawString(arraylist_type[i].ToString(), font1, brush1, new Point(225 - x, 225 - y));
  1417. // g.DrawString((Convert.ToInt32(arraylist_tp[i])).ToString() + "%", font1, brush1, new Point(225 - x, 225 - y + 12));
  1418. //}
  1419.  
  1420. //else if (tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 == 270)
  1421. //{
  1422. // g.DrawString(arraylist_type[i].ToString(), font1, brush1, new Point(225, 225 - 125));
  1423. // g.DrawString((Convert.ToInt32(arraylist_tp[i])).ToString() + "%", font1, brush1, new Point(225, 225 - 125 + 12));
  1424. //}
  1425.  
  1426. //else if (tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 > 270 && tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 < 360)
  1427. //{
  1428. // halfangle = (360 - tem_angle - Convert.ToSingle(arraylist_angle[i]) / 2);
  1429. // double tem_sin = Math.Sin(T / 180 * halfangle);
  1430. // double tem_cos = Math.Cos(T / 180 * halfangle);
  1431.  
  1432. // int y = Convert.ToInt32(125 * tem_sin);
  1433. // int x = Convert.ToInt32(125 * tem_cos);
  1434. // g.DrawString(arraylist_type[i].ToString(), font1, brush1, new Point(225 + x, 225 - y));
  1435. // g.DrawString((Convert.ToInt32(arraylist_tp[i])).ToString() + "%", font1, brush1, new Point(225 + x, 225 - y + 12));
  1436. //}
  1437.  
  1438. //else if (tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 == 360)
  1439. //{
  1440. // g.DrawString(arraylist_type[i].ToString(), font1, brush1, new Point(225 + 125, 225));
  1441. // g.DrawString((Convert.ToInt32(arraylist_tp[i])).ToString() + "%", font1, brush1, new Point(225 + 125, 225 + 12));
  1442. //}
  1443.  
  1444. // 累加角度
  1445. sumAngle += curAngle;
  1446.  
  1447. }
  1448.  
  1449. }
  1450. }
  1451.  
  1452. #endregion
  1453.  
  1454. #region 辅助方法
  1455.  
  1456. /// <summary>
  1457. /// 计算X轴刻度值最大高度
  1458. /// </summary>
  1459. /// <returns></returns>
  1460. private void Calc_XScaleHeight()
  1461. {
  1462. SizeF tmMaxSizeF = new SizeF(, );
  1463. for (int t = ; t < XScaleValues.Count; t++)
  1464. {
  1465. SizeF tmSizeF = g.MeasureString(XScaleValues[t], new Font("宋体", ));
  1466. if (tmSizeF.Width > tmMaxSizeF.Width)
  1467. {
  1468. tmMaxSizeF.Width = tmSizeF.Width;
  1469. tmMaxSizeF.Height = tmSizeF.Height;
  1470. }
  1471. }
  1472. myXScaleMaxHeight = (((float)Math.Sqrt(tmMaxSizeF.Height * tmMaxSizeF.Height + tmMaxSizeF.Width * tmMaxSizeF.Width) - tmMaxSizeF.Height) * XRotateAngle / + tmMaxSizeF.Height + 13f);
  1473. }
  1474.  
  1475. /// <summary>
  1476. /// 计算坐标Y轴的刻度值
  1477. /// 适用于:曲线图、柱状图
  1478. /// 不适用:饼状图无需计算
  1479. /// </summary>
  1480. private void Calc_YScaleValue()
  1481. {
  1482. myMaxValue = ; // 原始最大值
  1483. myMinValue = ; // 原始最小值
  1484.  
  1485. // 计算所有数据的最大值和最小值
  1486. for (int mm = ; mm < this.ChartDataArray.Count; mm++)
  1487. {
  1488. for (int nn = ; nn < this.ChartDataArray[mm].Values.Count; nn++)
  1489. {
  1490. double iData = this.ChartDataArray[mm].Values[nn];
  1491. if (mm == && nn == )
  1492. {
  1493. myMaxValue = iData;
  1494. myMinValue = iData;
  1495. }
  1496. else
  1497. {
  1498. myMaxValue = iData > myMaxValue ? iData : myMaxValue;
  1499. myMinValue = iData > myMinValue ? myMinValue : iData;
  1500. }
  1501. }
  1502. }
  1503.  
  1504. // 计算Y轴刻度
  1505. double tmMax_New = Math.Ceiling(myMaxValue); // 目标最大值 向上取整
  1506. double tmMin_New = Math.Floor(myMinValue); // 目标最小值 向下取整
  1507. if (myMinValue == )
  1508. {
  1509. YScale_SplitValue = Math.Ceiling(tmMax_New / (double)YSplitNum); // 计算Y轴刻度间隔值
  1510. YScale_StartValue = ; // 计算Y轴刻度开始值
  1511. }
  1512. else
  1513. {
  1514. // 计算间隔值
  1515. double tmJD1 = Math.Ceiling((tmMax_New - tmMin_New) / (double)(YSplitNum));
  1516. double tmJD2 = tmJD1 - Math.Ceiling((tmMax_New - tmMin_New) / (double)(YSplitNum + ));
  1517. if (tmJD1 == ) tmJD1 = ;
  1518. YScale_StartValue = tmJD1 * Math.Floor(tmMin_New / tmJD1); // 计算Y轴刻度开始值
  1519. bool tmJDFlag = true;
  1520. while (tmJDFlag)
  1521. {
  1522. if (YScale_StartValue <= tmMin_New && (YScale_StartValue + tmJD1 * YSplitNum) >= tmMax_New)
  1523. {
  1524. tmJDFlag = false;
  1525. YScale_SplitValue = tmJD1; // 计算Y轴刻度间隔值
  1526. break;
  1527. }
  1528. else
  1529. {
  1530. tmJD1 += tmJD2;
  1531. }
  1532. }
  1533. }
  1534.  
  1535. // 计算Y轴刻度字符串的最大宽度
  1536. SizeF tmYSizeF = g.MeasureString((YScale_StartValue + YScale_SplitValue * YSplitNum).ToString(), new Font("宋体", ));
  1537. myYScaleMaxWidth = tmYSizeF.Width + 9f;// 预留4个像素
  1538. }
  1539.  
  1540. #endregion
  1541.  
  1542. #region 枚举方法
  1543.  
  1544. /// <summary>
  1545. /// 枚举图表类型
  1546. /// </summary>
  1547. public enum EChartType
  1548. {
  1549. /// <summary>
  1550. /// 曲线图
  1551. /// </summary>
  1552. Curve,
  1553.  
  1554. /// <summary>
  1555. /// 柱状图
  1556. /// </summary>
  1557. Bar,
  1558.  
  1559. /// <summary>
  1560. /// 饼状图
  1561. /// </summary>
  1562. Pie
  1563.  
  1564. }
  1565.  
  1566. /// <summary>
  1567. /// 枚举对齐方式
  1568. /// </summary>
  1569. public enum EAlign
  1570. {
  1571.  
  1572. /// <summary>
  1573. /// 居左
  1574. /// </summary>
  1575. left,
  1576.  
  1577. /// <summary>
  1578. /// 居中
  1579. /// </summary>
  1580. center,
  1581.  
  1582. /// <summary>
  1583. /// 居右
  1584. /// </summary>
  1585. right
  1586. }
  1587.  
  1588. #endregion
  1589.  
  1590. }
  1591.  
  1592. /// <summary>
  1593. /// 图表数据单个项目
  1594. /// </summary>
  1595. public class EChartData
  1596. {
  1597. private string _name;
  1598. private List<double> _values;
  1599. private Color _itemColor;
  1600. private SizeF _nameSize;
  1601.  
  1602. public EChartData()
  1603. {
  1604. _name = "";
  1605. _values = new List<double>();
  1606. _itemColor = Color.White;
  1607. _nameSize = new SizeF(, );
  1608. }
  1609.  
  1610. /// <summary>
  1611. /// 项目名称
  1612. /// </summary>
  1613. public string Name
  1614. {
  1615. get { return _name; }
  1616. set { _name = value; }
  1617. }
  1618.  
  1619. /// <summary>
  1620. /// 项目值数组
  1621. /// </summary>
  1622. public List<double> Values
  1623. {
  1624. get { return _values; }
  1625. set { _values = value; }
  1626. }
  1627.  
  1628. /// <summary>
  1629. /// 文字大小
  1630. /// 用户绘制图例时候使用
  1631. /// </summary>
  1632. public SizeF NameSize
  1633. {
  1634. get { return _nameSize; }
  1635. set { _nameSize = value; }
  1636. }
  1637.  
  1638. /// <summary>
  1639. /// 项目颜色
  1640. /// </summary>
  1641. public Color ItemColor
  1642. {
  1643. get { return _itemColor; }
  1644. set { _itemColor = value; }
  1645. }
  1646.  
  1647. }
  1648. }

表报设计DLL控件的源码实在太多,这里就不再一一贴出来了,下载完整的源码自己调试运行查看。
   此报表设计器结合上次的WEB打印控件,就组成了完整的报表设计。

报表设计器实例完整源码下载地址:www.sdpsoft.com/==》下载中心==》报表设计器简易源码----自定义报表控件(源码)以及在Winform中的使用源码

或直接下载地址:winform报表设计工具源码

欢迎广大朋友一起交流。

C# 报表设计器 (winform 设计端)开发与实现生成网页的HTML报表的更多相关文章

  1. Web在线报表设计器使用指南

    市面上的报表工具有很多,虽说功能大同小异,但每一个报表工具都有各自明确的定位,选择最合适的工具,才能达到事半功倍的效果. 本文将要介绍的ActiveReports报表工具,可全面满足 .NET 报表开 ...

  2. 解析大型.NET ERP系统核心组件 查询设计器 报表设计器 窗体设计器 工作流设计器 任务计划设计器

    企业管理软件包含一些公共的组件,这些基础的组件在每个新项目立项阶段就必须考虑.核心的稳定不变功能,方便系统开发与维护,也为系统二次开发提供了诸多便利.比如通用权限管理系统,通用附件管理,通用查询等组件 ...

  3. 创建您的 ActiveReports Web端在线报表设计器

    概述 ActiveReports Web端在线报表设计器已经正式上线!看到它这么帅气.实用,你是不是也想自己动手创建一个? 现在我们就来教您,如何创建一个简单的 ActiveReports Web端在 ...

  4. Java开发报表——Grid++Report 报表设计器

    为了让数据显示的更加形象生动,报表在项目中差点儿是很常见的,可是大致能够分为两类: 一,图形:以图形的形式显示数据,比如柱状图,折线图,饼形图等等,这里有许多关于这方面的工具,比如JFreeChart ...

  5. 如何在CRM系统中集成ActiveReports最终报表设计器

    有时候,将ActiveReports设计器集成到业务系统中,为用户提供一些自定义的数据表,用户不需要了解如何底层的逻辑关系和后台代码,只需要选择几张关联的数据表,我们会根据用户的选择生成可供用户直接使 ...

  6. BIRT使用1:简介、概念、元素、报表设计器组成

    前一篇博客对birt进行了一个初探,相信通过上篇博客大家对birt有个初步认识,接下来我们随着下面这张思维导图的展示,进入birt的使用学习. 这一篇博客是第一部分,主要介绍一下birt的简介.概念. ...

  7. 在网页中编辑报表的报表设计器Stimulsoft Reports Designer.Web报表控件

    Stimulsoft Reports Designer.Web报表控件是一款网页报表设计器.您想在网页中编辑您的报表吗?现在是可能的! Stimulsoft Reports Designer.Web ...

  8. 机房收费系统中的Grid++Report报表设计器的应用

    在进行账单查询功能的时候我应用了Grid++Report报表设计器,下面我就为大家介绍一下,还望大家多多指点. 首先,在Grid++Report报表设计器中进行报表界面的设置.在属性编辑窗口中这里对报 ...

  9. H3BPM表单设计器公式设计参考

    表单设计器公式设计参考 整体说明 Ø 公式以javascript方式解析,最终支持JS语法或计算方式: Ø 公式变量以数据项为主,以{}符号表示数据项,例如数据项A,表示为{A}:如果是子表中的数据项 ...

随机推荐

  1. android 手机屏幕有关的几个工具(屏幕宽高,dp和px互相转换)

    平时适配页面时经常会需要根据屏幕的宽高来设置控件的大小,很多时候在代码中还会需要dp和px互相转换. 今天把最常用的几个记录一下,经测试包括2.3 ~ 5.0之间的版本都可用,其他版本未测,不过应该也 ...

  2. 关于MVC中Start.cs文件的作用

    当我们建立默认的 .NET Framework4.5.2框架下的Web  MVC 应用程序后,调试过程中我发现在程序启动页面加载完成会执行一段代码,这段代码让人有点摸不着头脑,因为之前完全没见过,调试 ...

  3. 八皇后—Java

    package queen; public class queen { static boolean col[] = new boolean[8]; static boolean main_diago ...

  4. 【Gerrit】Gerrit cmd query (gerrit命令行查询change信息)

    本文仅展现个人使用情况和理解,英文原址:https://review.openstack.org/Documentation/cmd-query.html 基本使用格式: ssh -p <por ...

  5. Exynos 4412

    Exynos 4412采用了三星最新的32nm HKMG工艺,是三星的第一款四核处理器 1.启动 有时间再接着写……

  6. 关于js代码中与或运算符||&&的妙用

    看bootstrap时看到如下一行JavaScript代码产生了疑惑. return window.pageYOffset || e.scrollTop ||在这里的作用是什么呢? 首先明确概念,在j ...

  7. A log about Reading the memroy of Other Process in C++/WIN API--ReadProcessMemory()

    Memory, is a complex module in Programing, especially on Windows. This time, I use cpp with win wind ...

  8. 各种模板(part 1)

    GCD: int gcd(int a,int b) { ?a:gcd(b,a%b); } 快速幂: void work(int x,int y) //x^y { ; ) { ==) ans=ans*x ...

  9. cf 732c

    /* cf732c 错过的最少次数 _________________________________________________________________________________ ...

  10. EXCEL导入(反射)

    import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import ja ...