C# 报表设计器 (winform 设计端)开发与实现生成网页的HTML报表
记得2010年之前,公司的项目基本上都要用到报表,以前我们常用的方法就是针对客户的需求来定制化开发(基本上是死写代码)来实现,经常导致项目经常性的延期,因为客户的需求经常会变化,随着用户的使用认知度的提高,对报表的要求越来越高,导致程序员不停的修改代码来实现,效率不高、结束遥遥无期。。。非常的痛苦;当然市面上有很多报表开发工具可以实现,但是针对小公司来说采购一套这样的系统的成本也非常的高,所以我们决定自己来开发一套像目前的润乾、FineReport 这样的报表设计器,来实现快速的报表设计制作。
当初为了开发这样的系统,花费的了很长的时间学习查阅各种资料,其痛苦只有程序员才能体会,因为没有任何现成的实例代码可供参考,只有看别人的思路来一步步的摸索,本文将我们当初设计制作的报表设计器的功能分享出来,让有需要的或想开发报表设计的朋友们提供一个参考,尽量少走很动弯路,设计端可以直接使用,但是计算引擎和网页的计算的源码就不能分享出来了(请不要介意,因为涉及到公司的保密原因)
记得当初为了制作报表设计器,在网上查找有没有相关的实例资料,找了很久,也是没有找到合适的,后来发现 SourceGrid 可以实现单元格的合并拆分功能,所以决定修改实现winform端的报表设计。下面我将制作的E_Report 报表控件抽取出来建立一个简易的Winform的可运行的实例提供给大伙下载,希望能给你的开发提供一点帮助和借鉴;当然你可以直接使用也可以,里面的设计功能基本全部能。
抽取出来的源码包含:E_Report 报表设计自定义控件DLL源码; EReportDemo 建立的简易Winform 端设计器使用DLL的实例源码;
一、运行效果
实例中,只做了一个简单的效果,工具栏的按钮在单元格右击属性中都有,只是放了几个常用的在工具导航栏中(右击单元格属性可以看到设计导航)
可以进行单元格的合并、拆分、字体、颜色、背景、边框等的设置,朋友们可以自己编写保存发布等功能,实现报表的真实功能;
例如单元格属性(其他还有很多的属性,自己下载源码后运行起来就能看到了)
对表格的斜线、斜线文字有很好的支持;可以设置表头、表位、标题等 实际效果图如下
二、使用介绍
1、页面初始化的时候,通过 ReportDoc 类 初始报表的行列及单元格属性
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Drawing;
- using System.Windows.Forms;
- using System.Drawing.Drawing2D;
- using System.Xml;
- using System.Collections;
- using E_Report;
- namespace EReportDemo
- {
- /// <summary>
- /// 报表表格对象
- /// </summary>
- public class ReportDoc
- {
- #region 变量参数定义
- /// <summary>
- /// 表格对象
- /// </summary>
- private EReport _nowReport;
- /// <summary>
- /// 报表配置编码
- /// </summary>
- private string _reportCode = "";
- /// <summary>
- /// 表报设计状态
- /// </summary>
- private string _reportState = "";
- #endregion
- #region 函数构造方法
- /// <summary>
- /// 构造函数
- /// </summary>
- public ReportDoc()
- {
- this._nowReport = null;
- this._reportCode = "";
- this._reportState = "";
- }
- /// <summary>
- /// 获取--设置--表格对象
- /// </summary>
- public EReport NowReport
- {
- get { return this._nowReport; }
- set { this._nowReport = value; }
- }
- /// <summary>
- /// 报表配置编码
- /// </summary>
- public string ReportCode
- {
- get { return this._reportCode; }
- set { this._reportCode = value; }
- }
- /// <summary>
- /// 报表设计状态
- /// 新增、修改 两种状态
- /// </summary>
- public string ReportState
- {
- get { return this._reportState; }
- set { this._reportState = value; }
- }
- /// <summary>
- /// 资源释放
- /// </summary>
- ~ReportDoc()
- {
- this._nowReport = null;
- this._reportState = "";
- }
- #endregion
- #region 加载报表表格
- /// <summary>
- /// 初始化--报表表格
- /// </summary>
- public void InitReport()
- {
- int rCount = ; // 41行
- int cCount = ; // 20列
- _nowReport.Redim(rCount, cCount);
- _nowReport.FixedRows = ;
- _nowReport.FixedColumns = ;
- InitCells();
- }
- /// <summary>
- /// 初始化--单元格
- /// </summary>
- public void InitCells()
- {
- // 第一行 第一列
- _nowReport.Rows[].Height = ;
- _nowReport.Columns[].Width = ;
- // 设置00格
- _nowReport[, ] = new E_Report.Cells.HeaderColumn("");
- // 设置行
- for (int rr = ; rr < _nowReport.RowsCount; rr++)
- {
- string tmRowT = rr.ToString();
- _nowReport[rr, ] = new E_Report.Cells.HeaderRow(tmRowT);
- }
- // 设置列
- for (int cc = ; cc < _nowReport.ColumnsCount; cc++)
- {
- _nowReport[, cc] = new E_Report.Cells.HeaderColumn(_nowReport.GetColumnHeadTileChar(cc));
- }
- // 设置单元格
- for (int iRow = ; iRow < _nowReport.RowsCount; iRow++)
- {
- for (int iCol = ; iCol < _nowReport.ColumnsCount; iCol++)
- {
- _nowReport[iRow, iCol] = new E_Report.Cells.Cell("", typeof(string));
- }
- }
- }
- #endregion
- }
- }
2、工具导航栏 设置单元格相关属性
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Drawing;
- using System.Text;
- using System.Windows.Forms;
- using System.Collections;
- using E_Report;
- namespace EReportDemo
- {
- /// <summary>
- /// 本程序只是Winform端的报表设计功能
- /// 至于其他的功能,本实例没有提供
- /// 报表设计的设计效果:可以查看 www.sdpsoft.com SDP软件快速开发平台 报表设计篇
- /// </summary>
- public partial class EReportMain : Form
- {
- private ReportDoc report;
- private E_Report.Cells.Controllers.PopupMenu myPopupMenu;
- public EReportMain()
- {
- InitializeComponent();
- }
- private void EReportMain_Load(object sender, EventArgs e)
- {
- Cursor.Current = Cursors.WaitCursor;
- gridMain.Rows.Clear();
- myPopupMenu = new E_Report.Cells.Controllers.PopupMenu(gridMain);
- report = new ReportDoc();
- report.NowReport = gridMain;
- report.InitReport();
- Cursor.Current = Cursors.Default;
- }
- private void gridMain_MouseMove(object sender, MouseEventArgs e)
- {
- this.lbl_X.Text = e.X.ToString();
- this.lbl_Y.Text = e.Y.ToString();
- }
- /// <summary>
- /// 工具栏报表单元格事件
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void btn_GridTools_Click(object sender, EventArgs e)
- {
- string sType = ((Button)sender).Tag.ToString().Trim().ToLower();
- switch (sType)
- {
- case "cellproperty": // 单元格属性设置
- myPopupMenu.CellProperty_Click(sender, e);
- break;
- case "fontset": // 单元格字体设置
- myPopupMenu.CellFont_Click(sender, e);
- break;
- case "fontcolor": // 文本字体颜色
- myPopupMenu.CellForColor_Click(sender, e);
- break;
- case "backcolor": // 单元格背景色
- myPopupMenu.CellBackColor_Click(sender, e);
- break;
- case "cellborder": // 单元格边框设置
- myPopupMenu.CellBorder_Click(sender, e);
- break;
- case "lock": // 设置表格只读
- myPopupMenu.LockReport_Click(sender, e);
- break;
- case "unlock": // 设置表格编辑
- myPopupMenu.UnLockReport_Click(sender, e);
- break;
- case "alignleft": // 水平居左对齐
- myPopupMenu.AlignLeft_Click(sender, e);
- break;
- case "aligncenter": // 水平居中对齐
- myPopupMenu.AlignCenter_Click(sender, e);
- break;
- case "alignright": // 水平居右对齐
- myPopupMenu.AlignRight_Click(sender, e);
- break;
- case "aligntop": // 垂直居上对齐
- myPopupMenu.AlignTop_Click(sender, e);
- break;
- case "alignmiddle": // 垂直居中对齐
- myPopupMenu.AlignMiddle_Click(sender, e);
- break;
- case "alignbottom": // 垂直居下对齐
- myPopupMenu.AlignBottom_Click(sender, e);
- break;
- case "addindent": // 增加文本缩进
- myPopupMenu.AddIndent_Click(sender, e);
- break;
- case "delindent": // 清除文本缩进
- myPopupMenu.RemoveIndent_Click(sender, e);
- break;
- case "insertrow": // 插入后一行
- myPopupMenu.InsertRow_Click(sender, e);
- break;
- case "appendrow": // 表格追加行
- myPopupMenu.AddRow_Click(sender, e);
- break;
- case "delrow": // 删除选中行
- myPopupMenu.DeleteRows_Click(sender, e);
- break;
- case "hiderow": // 隐藏选中行
- myPopupMenu.HideSelectRows_Click(sender, e);
- break;
- case "showrow": // 显示选中行
- myPopupMenu.ShowSelectRows_Click(sender, e);
- break;
- case "showallrow": // 显示所有行
- myPopupMenu.ShowAllRows_Click(sender, e);
- break;
- case "insertcol": // 插入左侧列
- myPopupMenu.InsertColumn_Click(sender, e);
- break;
- case "addcol": // 插入右侧列
- myPopupMenu.AddColumn_Click(sender, e);
- break;
- case "delcol": // 删除选中列
- myPopupMenu.DeleteColumns_Click(sender, e);
- break;
- case "hidecol": // 隐藏选中列
- myPopupMenu.HideSelectColumns_Click(sender, e);
- break;
- case "showcol": // 显示选中列
- myPopupMenu.ShowSelectColumns_Click(sender, e);
- break;
- case "showallcol": // 显示所有列
- myPopupMenu.ShowAllColumns_Click(sender, e);
- break;
- case "mergecell": // 合并单元格
- myPopupMenu.MergeCell_Click(sender, e);
- break;
- case "splitcell": // 拆分单元格
- myPopupMenu.SplitCell_Click(sender, e);
- break;
- }
- }
- }
- }
3、报表控件DLL类库部分
里面有我们自定义的 条码控件、图片控件、图表控件
表格内自定义图表控件(曲线、柱状、饼状)源码
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Drawing.Text;
- namespace E_Report
- {
- /// <summary>
- /// 图表属性
- /// </summary>
- /// <summary>
- /// 报表图表类库
- /// </summary>
- public class EChart
- {
- #region 属性方法
- #region 临时变量
- /// <summary>
- /// 临时变量--关联单元格行号
- /// </summary>
- private int _row = ;
- /// <summary>
- /// 获取--设置--关联单元格行号
- /// </summary>
- public int Row
- {
- get { return _row; }
- set { _row = value; }
- }
- /// <summary>
- /// 临时变量--关联单元格列号
- /// </summary>
- private int _col = ;
- /// <summary>
- /// 获取--设置--关联单元格列号
- /// </summary>
- public int Col
- {
- get { return _col; }
- set { _col = value; }
- }
- /// <summary>
- /// 数据来源
- /// </summary>
- private string _t_DataFrom = "数据源";
- /// <summary>
- /// 获取--设置--数据来源
- /// </summary>
- public string T_DataFrom
- {
- get { return _t_DataFrom; }
- set { _t_DataFrom = value; }
- }
- /// <summary>
- /// 数据源名称
- /// </summary>
- private string _t_DsName = "";
- /// <summary>
- /// 获取--设置--数据源名称
- /// </summary>
- public string T_DsName
- {
- get { return _t_DsName; }
- set { _t_DsName = value; }
- }
- /// <summary>
- /// 项目名称
- /// </summary>
- private string _t_ItemName = "";
- /// <summary>
- /// 获取--设置--项目名称
- /// </summary>
- public string T_ItemName
- {
- get { return _t_ItemName; }
- set { _t_ItemName = value; }
- }
- /// <summary>
- /// 项目数值
- /// </summary>
- private string _t_ItemValue = "";
- /// <summary>
- /// 获取--设置--项目数值
- /// </summary>
- public string T_ItemValue
- {
- get { return _t_ItemValue; }
- set { _t_ItemValue = value; }
- }
- /// <summary>
- /// X轴刻度
- /// </summary>
- private string _t_XScale = "";
- /// <summary>
- /// 获取--设置--X轴刻度
- /// </summary>
- public string T_XScale
- {
- get { return _t_XScale; }
- set { _t_XScale = value; }
- }
- #endregion
- #region 图表属性
- /// <summary>
- /// 图表名称ID
- /// </summary>
- private string _name = "";
- /// <summary>
- /// 获取--设置--图表名称ID
- /// </summary>
- public string Name
- {
- get { return _name; }
- set { _name = value; }
- }
- /// <summary>
- /// 图表类型
- /// </summary>
- private EChartType _chartType = EChartType.Curve;
- /// <summary>
- /// 获取--设置--图表类型
- /// 默认:Line 折曲线
- /// </summary>
- public EChartType ChartType
- {
- get { return _chartType; }
- set { _chartType = value; }
- }
- /// <summary>
- /// 图表宽度
- /// </summary>
- private int _chartWidth = ;
- /// <summary>
- /// 获取--设置--图表宽度
- /// </summary>
- public int ChartWidth
- {
- get { return _chartWidth; }
- set { _chartWidth = value; }
- }
- /// <summary>
- /// 图表高度
- /// </summary>
- private int _chartHeight = ;
- /// <summary>
- /// 获取--设置--图表高度
- /// </summary>
- public int ChartHeight
- {
- get { return _chartHeight; }
- set { _chartHeight = value; }
- }
- /// <summary>
- /// 图表背景颜色
- /// </summary>
- private Color _backColor = Color.White;
- /// <summary>
- /// 获取--设置--图表背景颜色
- /// </summary>
- public Color BackColor
- {
- get { return _backColor; }
- set { _backColor = value; }
- }
- /// <summary>
- /// 是否显示图表边框
- /// </summary>
- private bool _showBorder = true;
- /// <summary>
- /// 获取--设置--是否显示图表边框
- /// 默认:true 显示
- /// </summary>
- public bool ShowBorder
- {
- get { return _showBorder; }
- set { _showBorder = value; }
- }
- /// <summary>
- /// 图表边框颜色
- /// </summary>
- private Color _borderColor = Color.LightGray;
- /// <summary>
- /// 获取--设置--图表边框颜色
- /// </summary>
- public Color BorderColor
- {
- get { return _borderColor; }
- set { _borderColor = value; }
- }
- /// <summary>
- /// 是否显示网格线
- /// </summary>
- private bool _showGrid = true;
- /// <summary>
- /// 获取--设置--是否显示网格线
- /// 默认:true 显示
- /// </summary>
- public bool ShowGrid
- {
- get { return _showGrid; }
- set { _showGrid = value; }
- }
- /// <summary>
- /// 线条张力系数
- /// </summary>
- private float _lineTension = 0.3f;
- /// <summary>
- /// 获取--设置--线条张力系数
- /// 默认:0.3
- /// </summary>
- public float LineTension
- {
- get { return _lineTension; }
- set
- {
- if (value < 0.0f && value > 1.0f)
- _lineTension = 0.5f;
- else
- _lineTension = value;
- }
- }
- #endregion
- #region 标题属性
- /// <summary>
- /// 是否显示主标题
- /// </summary>
- private bool _showTitle = true;
- /// <summary>
- /// 获取--设置--是否显示主标题
- /// 默认:true 显示
- /// </summary>
- public bool ShowTitle
- {
- get { return _showTitle; }
- set { _showTitle = value; }
- }
- /// <summary>
- /// 主标题文本
- /// </summary>
- private string _title = "";
- /// <summary>
- /// 获取--设置--主标题文本
- /// </summary>
- public string Title
- {
- get { return _title; }
- set { _title = value; }
- }
- /// <summary>
- /// 主标题字体
- /// </summary>
- private Font _titleFont = new Font("黑体", );
- /// <summary>
- /// 获取--设置--主标题字体
- /// </summary>
- public Font TitleFont
- {
- get { return _titleFont; }
- set { _titleFont = value; }
- }
- /// <summary>
- /// 主标题颜色
- /// </summary>
- private Color _titleColor = Color.Black;
- /// <summary>
- /// 获取--设置--主标题颜色
- /// </summary>
- public Color TitleColor
- {
- get { return _titleColor; }
- set { _titleColor = value; }
- }
- /// <summary>
- /// 主标题对齐方式
- /// </summary>
- private EAlign _titleAlign = EAlign.center;
- /// <summary>
- /// 获取--设置--主标题对齐方式
- /// </summary>
- public EAlign TitleAlign
- {
- get { return _titleAlign; }
- set { _titleAlign = value; }
- }
- /// <summary>
- /// 是否显示副标题
- /// </summary>
- private bool _showSubTilte = true;
- /// <summary>
- /// 获取--设置--是否显示副标题
- /// 默认:true 显示
- /// </summary>
- public bool ShowSubTitle
- {
- get { return _showSubTilte; }
- set { _showSubTilte = value; }
- }
- /// <summary>
- /// 副标题文本
- /// </summary>
- private string _subTitle = "";
- /// <summary>
- /// 获取--设置--副标题文本
- /// </summary>
- public string SubTitle
- {
- get { return _subTitle; }
- set { _subTitle = value; }
- }
- /// <summary>
- /// 副标题字体
- /// </summary>
- private Font _subTitleFont = new Font("黑体", );
- /// <summary>
- /// 获取--设置--副标题字体
- /// </summary>
- public Font SubTitleFont
- {
- get { return _subTitleFont; }
- set { _subTitleFont = value; }
- }
- /// <summary>
- /// 副标题颜色
- /// </summary>
- private Color _subTitleColor = Color.Blue;
- /// <summary>
- /// 获取--设置--副标题颜色
- /// </summary>
- public Color SubTitleColor
- {
- get { return _subTitleColor; }
- set { _subTitleColor = value; }
- }
- /// <summary>
- /// 副标题对齐方式
- /// </summary>
- private EAlign _subTitleAlign = EAlign.center;
- /// <summary>
- /// 获取--设置--副标题对齐方式
- /// </summary>
- public EAlign SubTitleAlign
- {
- get { return _subTitleAlign; }
- set { _subTitleAlign = value; }
- }
- /// <summary>
- /// 副标题水平方向偏移量
- /// + - 整数
- /// </summary>
- private int _subTitleOffset = ;
- /// <summary>
- /// 获取--设置--副标题水平方向偏移量
- /// </summary>
- public int SubTitleOffset
- {
- get { return _subTitleOffset; }
- set { _subTitleOffset = value; }
- }
- #endregion
- #region 图例属性
- /// <summary>
- /// 是否显示图例
- /// </summary>
- private bool _showLegend = true;
- /// <summary>
- /// 是否显示图例
- /// </summary>
- public bool ShowLegend
- {
- get { return _showLegend; }
- set { _showLegend = value; }
- }
- /// <summary>
- /// 图例字体
- /// </summary>
- private Font _legendFont = new Font("宋体", );
- /// <summary>
- /// 获取--设置--图例字体
- /// </summary>
- public Font LegendFont
- {
- get { return _legendFont; }
- set { _legendFont = value; }
- }
- /// <summary>
- /// 图例字体颜色
- /// </summary>
- private Color _legendColor = Color.Black;
- /// <summary>
- /// 获取--设置--图例字体颜色
- /// </summary>
- public Color LegendColor
- {
- get { return _legendColor; }
- set { _legendColor = value; }
- }
- /// <summary>
- /// 图例对齐方式
- /// </summary>
- private EAlign _legendAlign = EAlign.center;
- /// <summary>
- /// 获取--设置--图例对齐方式
- /// </summary>
- public EAlign LegendAlign
- {
- get { return _legendAlign; }
- set { _legendAlign = value; }
- }
- #endregion
- #region 坐标属性
- /// <summary>
- /// 获取--X轴分割段数
- /// </summary>
- public int XSplitNum
- {
- get { return _xScaleValues.Count; }
- }
- /// <summary>
- /// Y轴分割段数
- /// </summary>
- private int _ySplitNum = ;
- /// <summary>
- /// 获取--设置--分割段数
- /// 默认:5
- /// 范围:最小5
- /// </summary>
- public int YSplitNum
- {
- get { return _ySplitNum; }
- set
- {
- if (value < )
- _ySplitNum = ;
- else
- _ySplitNum = value;
- }
- }
- /// <summary>
- /// X 轴标
- /// </summary>
- private string _xAxisText = "";
- /// <summary>
- /// 获取--设置--X 轴标
- /// </summary>
- public string XAxisText
- {
- get { return _xAxisText; }
- set { _xAxisText = value; }
- }
- /// <summary>
- /// Y 轴标
- /// </summary>
- private string _yAxisText = "";
- /// <summary>
- /// 获取--设置--Y 轴标
- /// </summary>
- public string YAxisText
- {
- get { return _yAxisText; }
- set { _yAxisText = value; }
- }
- /// <summary>
- /// X轴文本旋转角度
- /// 默认:0
- /// 范围:0~90
- /// </summary>
- private float _xRotateAngle = 0.0f;
- /// <summary>
- /// 获取--设置--X轴文本旋转角度
- /// </summary>
- public float XRotateAngle
- {
- get { return _xRotateAngle; }
- set
- {
- if (value >= 0.0f && value <= 90.0f)
- _xRotateAngle = value;
- else
- _xRotateAngle = 0.0f;
- }
- }
- #endregion
- #region 绘图变量
- /// <summary>
- /// 绘图对象
- /// </summary>
- private Graphics g = null;
- /// <summary>
- /// 图表颜色数组
- /// </summary>
- private static Color[] ChartColor = {
- Color.Red, Color.Blue, Color.Orange, Color.Green, Color.Cyan, Color.Purple,
- Color.Coral, Color.Chocolate, Color.Gray, Color.Gold, Color.Lavender, Color.Linen,
- Color.Magenta, Color.Moccasin, Color.Navy, Color.Olive, Color.Peru, Color.Plum,
- Color.Purple, Color.Salmon, Color.Sienna, Color.Silver, Color.Tan, Color.Tomato,
- Color.Violet, Color.Turquoise, Color.Transparent
- };
- /// <summary>
- /// 边距10px
- /// </summary>
- private float Margin = ;
- /// <summary>
- /// 起点 X 坐标
- /// </summary>
- private float Start_X = ;
- /// <summary>
- /// 起点 Y 坐标
- /// </summary>
- private float Start_Y = ;
- /// <summary>
- /// 终点 X 坐标
- /// </summary>
- private float End_X = ;
- /// <summary>
- /// 终点 Y 坐标
- /// </summary>
- private float End_Y = ;
- /// <summary>
- /// X轴刻度宽度
- /// </summary>
- private float XScaleWidth = ;
- /// <summary>
- /// Y轴刻度宽度
- /// </summary>
- private float YScaleWidth = ;
- /// <summary>
- /// Y轴刻度间隔值
- /// 说明:Y轴坐标全部采用整数,表示每个间隔的计算单位值
- /// 包含正负数
- /// </summary>
- private double YScale_SplitValue = ;
- /// <summary>
- /// Y轴刻度开始值
- /// </summary>
- private double YScale_StartValue = ;
- /// <summary>
- /// 坐标轴原点坐标
- /// </summary>
- private PointF AxisZeroPt = new PointF(0f, 0f);
- /// <summary>
- /// 图表数据
- /// </summary>
- private string _chartData = "";
- /// <summary>
- /// 获取--设置--图表数据
- /// </summary>
- public string ChartData
- {
- get { return _chartData; }
- set { _chartData = value; }
- }
- /// <summary>
- /// 绘图笔刷
- /// </summary>
- private Brush brush;
- /// <summary>
- /// 绘制画笔
- /// </summary>
- private Pen pen;
- /// <summary>
- /// 绘图矩形
- /// </summary>
- private RectangleF rectF = new RectangleF(, , , );
- /// <summary>
- /// 字符格式化
- /// </summary>
- private StringFormat stringFormat;
- /// <summary>
- /// 临时变量 最大值
- /// </summary>
- private double myMaxValue = ;
- /// <summary>
- /// 临时变量 最小值
- /// </summary>
- private double myMinValue = ;
- /// <summary>
- /// 临时变量 X轴刻度最大高度
- /// 用于绘制坐标轴的时候进行偏移
- /// </summary>
- private float myXScaleMaxHeight = ;
- /// <summary>
- /// 临时变量 Y轴刻度值字符串的最大宽度
- /// 用于绘制坐标轴的时候进行偏移
- /// </summary>
- private float myYScaleMaxWidth = ;
- #endregion
- #region 图表数据
- /// <summary>
- /// X轴刻度值数组
- /// </summary>
- private List<string> _xScaleValues = new List<string>();
- /// <summary>
- /// 获取--设置--X轴刻度值数组
- /// </summary>
- public List<string> XScaleValues
- {
- get { return _xScaleValues; }
- set { _xScaleValues = value; }
- }
- /// <summary>
- /// 图表数据
- /// </summary>
- private List<EChartData> _chartDataArray = new List<EChartData>();
- /// <summary>
- /// 获取--设置--图表数据
- /// </summary>
- public List<EChartData> ChartDataArray
- {
- get { return _chartDataArray; }
- set { _chartDataArray = value; }
- }
- #endregion
- #endregion
- #region 构造方法
- /// <summary>
- /// 构造函数
- /// </summary>
- public EChart()
- {
- }
- /// <summary>
- /// 构造函数
- /// </summary>
- /// <param name="eChart"></param>
- public EChart(EChart eChart)
- {
- }
- #endregion
- #region 生成图表
- /// <summary>
- /// 生成图表
- /// </summary>
- /// <returns>返回:图表图像</returns>
- public Bitmap CreateImage()
- {
- Bitmap ChartImage = new Bitmap(ChartWidth, ChartHeight);
- g = Graphics.FromImage(ChartImage);
- g.SmoothingMode = SmoothingMode.Default;
- g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
- g.Clear(Color.White);
- Start_X = Margin;
- Start_Y = Margin;
- End_X = ChartWidth - Margin;
- End_Y = ChartHeight - Margin;
- DrawChart();
- g.Dispose();
- return ChartImage;
- }
- #endregion
- #region 绘制方法
- /// <summary>
- /// 绘制图表
- /// </summary>
- private void DrawChart()
- {
- DrawChart_InitGraph();
- DrawChart_MainTitle();
- DrawChart_SubTitle();
- DrawChart_Legend();
- DrawChart_YAxisText();
- if (ChartType != EChartType.Pie)
- {
- DrawChart_Axis();
- if (ChartType == EChartType.Curve)
- DrawChart_Curve();
- else
- DrawChart_Bar();
- }
- else
- {
- DrawChart_Pie();
- }
- }
- /// <summary>
- /// 绘制图表--绘制背景图
- /// </summary>
- private void DrawChart_InitGraph()
- {
- // 绘制图表外围边框
- if (_showBorder)
- g.DrawRectangle(new Pen(BorderColor, ), , , (ChartWidth - ), (ChartHeight - ));
- // 填充图表背景颜色
- g.FillRectangle(new SolidBrush(BackColor), , , ChartWidth - , ChartHeight - );
- }
- /// <summary>
- /// 绘制图表--绘制主标题
- /// </summary>
- private void DrawChart_MainTitle()
- {
- if (ShowTitle)
- {
- if (Title != null && Title.Trim() != "")
- {
- brush = new SolidBrush(TitleColor); // 矩形填充笔刷
- SizeF sizeF = g.MeasureString(Title, TitleFont); // 测试字体大小
- stringFormat = new StringFormat(); // 格式化字符串
- stringFormat.LineAlignment = StringAlignment.Center; // 垂直对齐方式
- switch (TitleAlign) // 水平对齐方式
- {
- case EAlign.center:
- stringFormat.Alignment = StringAlignment.Center;
- break;
- case EAlign.right:
- stringFormat.Alignment = StringAlignment.Far;
- break;
- default:
- stringFormat.Alignment = StringAlignment.Near;
- break;
- }
- rectF = new RectangleF(Start_X, Start_Y, (float)(ChartWidth - ), sizeF.Height); // 文字的矩形
- g.DrawString(Title, TitleFont, brush, rectF, stringFormat); // 绘制主标题
- Start_Y += sizeF.Height + 3f; // 设置Y起点值 + 3px
- }
- }
- }
- /// <summary>
- /// 绘制图表--绘制副标题
- /// </summary>
- private void DrawChart_SubTitle()
- {
- if (ShowSubTitle)
- {
- if (SubTitle != null && SubTitle.Trim() != "")
- {
- brush = new SolidBrush(SubTitleColor); // 矩形填充笔刷
- SizeF sizeF = g.MeasureString(SubTitle, SubTitleFont); // 测试字体大小
- stringFormat = new StringFormat(); // 格式化字符串
- stringFormat.LineAlignment = StringAlignment.Center; // 垂直对齐方式
- switch (SubTitleAlign) // 水平对齐方式
- {
- case EAlign.center:
- stringFormat.Alignment = StringAlignment.Center;
- break;
- case EAlign.right:
- stringFormat.Alignment = StringAlignment.Far;
- break;
- default:
- stringFormat.Alignment = StringAlignment.Near;
- break;
- }
- rectF = new RectangleF(Start_X + (float)SubTitleOffset, Start_Y, (float)(ChartWidth - ), sizeF.Height); // 文字的矩形
- g.DrawString(SubTitle, SubTitleFont, brush, rectF, stringFormat); // 绘制副标题
- Start_Y += sizeF.Height + 3f; // 设置Y起点值 + 3px
- }
- }
- }
- /// <summary>
- /// 绘制图表--绘制图例
- /// </summary>
- private void DrawChart_Legend()
- {
- // 计算项目颜色
- int tmIndex = ;
- for (int m = ; m < ChartDataArray.Count; m++)
- {
- tmIndex = m % ChartColor.Length;
- ChartDataArray[m].ItemColor = ChartColor[tmIndex];
- }
- // 图例的高度最大40px 3排
- if (ShowLegend)
- {
- // 计算文字大小
- int LegendCount = ChartDataArray.Count;
- Font tFont = new Font("宋体", );
- for (int t = ; t < LegendCount; t++)
- {
- SizeF tmSize = new SizeF();
- tmSize = g.MeasureString(ChartDataArray[t].Name, tFont);
- ChartDataArray[t].NameSize = tmSize;
- }
- #region 绘制一排图例
- // 首先判定一行够不够
- float largMax = ;
- for (int t = ; t < LegendCount; t++)
- {
- if (t == )
- largMax += ChartDataArray[t].NameSize.Width;
- else
- largMax += (35f + ChartDataArray[t].NameSize.Width);
- }
- if (largMax <= End_X - Start_X) // 图例只需一排
- {
- End_Y -= 12.0f;
- float tmX = (End_X - Start_X - largMax) / + Start_X;
- float tmY = End_Y;
- for (int n = ; n < LegendCount; n++)
- {
- g.FillRectangle(new SolidBrush(ChartDataArray[n].ItemColor), tmX, tmY + , , );
- tmX += ;
- g.DrawString(ChartDataArray[n].Name, new Font("宋体", ), new SolidBrush(Color.Black), tmX, tmY);
- tmX += + ChartDataArray[n].NameSize.Width;
- }
- }
- #endregion
- #region 绘制多排图例
- // 图例最多绘制三排
- else
- {
- bool TwoLine = true; // 是否两行:true 是; false: 否,为三行
- // 判定两排还是三排
- float tmBX = Start_X - ;
- int tmBC = (int)Math.Ceiling((double)LegendCount / );
- for (int T = ; T < tmBC; T++)
- {
- float tmBW1 = -1F, tmBW2 = -1F, tmBM = 0F;
- tmBW1 = ChartDataArray[T * ].NameSize.Width;
- if (ChartDataArray.Count > (T * + ))
- tmBW2 = ChartDataArray[T * + ].NameSize.Width;
- tmBM = tmBW1 > tmBW2 ? tmBW1 : tmBW2;
- tmBX += + tmBM;
- if (tmBX > (End_X + ))
- {
- TwoLine = false;
- break;
- }
- }
- // 绘制两排图例
- if (TwoLine)
- {
- End_Y -= 24.0f;
- float tmTX = (End_X + - tmBX + Start_X + ) / ; // 开始位置保持两排水平居中
- float tmTY = End_Y;
- int tmTM = (int)Math.Ceiling((double)LegendCount / );
- // 绘制两排图例
- for (int T = ; T < tmTM; T++)
- {
- float tmTW1 = -1F, tmTW2 = -1F, tmTW3 = 0F;
- tmTW1 = ChartDataArray[T * ].NameSize.Width;
- if (ChartDataArray.Count > (T * + ))
- tmTW2 = ChartDataArray[T * + ].NameSize.Width;
- tmTW3 = tmTW1 > tmTW2 ? tmTW1 : tmTW2;
- // 绘制第一排图例
- g.FillRectangle(new SolidBrush(ChartDataArray[T * ].ItemColor), tmTX, tmTY + , , );
- g.DrawString(ChartDataArray[T * ].Name, new Font("宋体", ), new SolidBrush(Color.Black), (tmTX + ), tmTY);
- // 绘制第二排图例
- if (tmTW2 > )
- {
- g.FillRectangle(new SolidBrush(ChartDataArray[T * + ].ItemColor), tmTX, (tmTY + + ), , );
- g.DrawString(ChartDataArray[T * + ].Name, new Font("宋体", ), new SolidBrush(Color.Black), (tmTX + ), (tmTY + ));
- }
- tmTX += + tmTW3;
- }
- }
- // 绘制三排图例
- else
- {
- End_Y -= 40.0f;
- // 如果三排还不够,那么就不管了,绘制超出范围就超出范围
- float tmSX = Start_X - ;
- float tmSY = End_Y;
- int tmSC = (int)Math.Ceiling((double)LegendCount / );
- bool CanFlag = true; // 三排是否足够
- // 首先计算三排的能排下的居中位置
- for (int n = ; n < tmSC; n++)
- {
- float tmSW1 = -1F, tmSW2 = -1F, tmSW3 = -1F, tmSW4 = 0F;
- tmSW1 = ChartDataArray[n * ].NameSize.Width;
- if (ChartDataArray.Count > (n * + ))
- tmSW2 = ChartDataArray[n * + ].NameSize.Width;
- if (ChartDataArray.Count > (n * + ))
- tmSW3 = ChartDataArray[n * + ].NameSize.Width;
- tmSW4 = tmSW1 > tmSW2 ? tmSW1 : tmSW2;
- tmSW4 = tmSW4 > tmSW3 ? tmSW4 : tmSW3;
- tmSX += + tmSW4;
- if (tmSX > (End_X + ))
- {
- CanFlag = false;
- break;
- }
- }
- // 再次执行三排绘制
- if (CanFlag) // 三排足够,则设置居中开始位置
- tmSX = (End_X + - tmSX + Start_X + ) / ;
- else
- tmSX = Start_X - ; // 三排排不下的情况就从5px 开始
- for (int n = ; n < tmSC; n++)
- {
- float tmSW1 = -1F, tmSW2 = -1F, tmSW3 = -1F, tmSW4 = 0F;
- tmSW1 = ChartDataArray[n * ].NameSize.Width;
- if (ChartDataArray.Count > (n * + ))
- tmSW2 = ChartDataArray[n * + ].NameSize.Width;
- if (ChartDataArray.Count > (n * + ))
- tmSW3 = ChartDataArray[n * + ].NameSize.Width;
- tmSW4 = tmSW1 > tmSW2 ? tmSW1 : tmSW2;
- tmSW4 = tmSW4 > tmSW3 ? tmSW4 : tmSW3;
- // 绘制第一排图例
- g.FillRectangle(new SolidBrush(ChartDataArray[n * ].ItemColor), tmSX, (tmSY + ), , );
- g.DrawString(ChartDataArray[n * ].Name, new Font("宋体", ), new SolidBrush(Color.Black), (tmSX + ), tmSY);
- // 绘制第二排图例
- if (tmSW2 > )
- {
- g.FillRectangle(new SolidBrush(ChartDataArray[n * + ].ItemColor), tmSX, (tmSY + + ), , );
- g.DrawString(ChartDataArray[n * + ].Name, new Font("宋体", ), new SolidBrush(Color.Black), (tmSX + ), (tmSY + ));
- }
- // 绘制第三排图例
- if (tmSW3 > )
- {
- g.FillRectangle(new SolidBrush(ChartDataArray[n * + ].ItemColor), tmSX, (tmSY + + ), , );
- g.DrawString(ChartDataArray[n * + ].Name, new Font("宋体", ), new SolidBrush(Color.Black), (tmSX + ), (tmSY + ));
- }
- tmSX += + tmSW4;
- }
- }
- }
- #endregion
- }
- }
- /// <summary>
- /// 绘制图表--绘制X轴标
- /// </summary>
- /// <param name="g"></param>
- private void DrawChart_XAxisText()
- {
- // X轴标就不绘制了,因为空间不够,所以不执行X轴标的绘制
- }
- /// <summary>
- /// 绘制图表--绘制Y轴标
- /// </summary>
- private void DrawChart_YAxisText()
- {
- if (ChartType != EChartType.Pie)
- {
- if (YAxisText != null && YAxisText.Trim() != "")
- {
- brush = new SolidBrush(Color.Gray);
- stringFormat = new StringFormat(); // 格式化字符串
- stringFormat.LineAlignment = StringAlignment.Near; // 垂直对齐方式
- stringFormat.Alignment = StringAlignment.Near; // 水平对齐方式
- SizeF sizeF = g.MeasureString(YAxisText, new Font("宋体", )); // 测量文字大小
- rectF = new RectangleF(Start_X, Start_Y, sizeF.Width, sizeF.Height); // 文字外围矩形
- g.TranslateTransform((Start_X - Start_Y), (Start_X + Start_Y + sizeF.Width)); // 设置位置移动 X,Y
- g.RotateTransform(); // 旋转270度 以左上角作为旋转原点
- g.DrawString(YAxisText, new Font("宋体", ), brush, rectF, stringFormat);
- g.ResetTransform();
- Start_X += sizeF.Height + ; // 加2个像素
- }
- }
- }
- /// <summary>
- /// 绘制图表--绘制坐标轴
- /// </summary>
- private void DrawChart_Axis()
- {
- // 1、图表区下移10PX
- Start_Y += ;
- // 2、计算坐标轴参数
- Calc_XScaleHeight();
- Calc_YScaleValue();
- // 3、计算原点坐标值
- AxisZeroPt = new PointF(0f, 0f); // 坐标轴原点坐标
- AxisZeroPt.X = Start_X + myYScaleMaxWidth;
- AxisZeroPt.Y = End_Y - myXScaleMaxHeight;
- // 3.1、绘制坐标轴
- Pen pen2 = new Pen(Color.FromKnownColor(KnownColor.ControlDark), 2f);
- g.DrawLine(pen2, (Start_X + myYScaleMaxWidth - 4f), (End_Y - myXScaleMaxHeight), End_X + , (End_Y - myXScaleMaxHeight)); // 绘制 X坐标轴
- g.DrawLine(pen2, (Start_X + myYScaleMaxWidth), (End_Y - myXScaleMaxHeight + 4f), (Start_X + myYScaleMaxWidth), Start_Y - ); // 绘制 Y坐标轴
- // 3.2、计算分段宽
- XScaleWidth = (End_X - Start_X - myYScaleMaxWidth) / XSplitNum; // 计算X轴分段宽
- YScaleWidth = (End_Y - Start_Y - myXScaleMaxHeight) / YSplitNum; // 计算Y轴分段宽
- // 3.3、绘制刻度值
- pen = new Pen(Color.LightGray, 1f);
- pen.DashStyle = DashStyle.Dash;
- for (int k = ; k < XSplitNum; k++) // 绘制X轴刻度线 刻度值
- {
- // 绘制X轴刻度线
- g.DrawLine(pen2, (AxisZeroPt.X + XScaleWidth * (k + )), AxisZeroPt.Y, (AxisZeroPt.X + XScaleWidth * (k + )), AxisZeroPt.Y + 4f);
- // 绘制X轴刻度值
- g.TranslateTransform(AxisZeroPt.X + XScaleWidth * k + 15f * XRotateAngle / + 4f, AxisZeroPt.Y + 4f); // 平移原点
- g.RotateTransform(XRotateAngle, MatrixOrder.Prepend); // 旋转图像
- g.DrawString(XScaleValues[k], new Font("宋体", 9f), new SolidBrush(Color.Black), , ); // 绘制字符
- g.ResetTransform();
- }
- for (int k = ; k < YSplitNum; k++)
- {
- // 绘制Y轴刻度线
- g.DrawLine(pen2, AxisZeroPt.X - , (AxisZeroPt.Y - YScaleWidth * (k + )), AxisZeroPt.X, (AxisZeroPt.Y - YScaleWidth * (k + )));
- // 绘制Y轴刻度值
- string tmYvalue = (YScale_StartValue + k * YScale_SplitValue).ToString();
- SizeF tmF = g.MeasureString(tmYvalue, new Font("宋体", ));
- g.DrawString(tmYvalue, new Font("宋体", ), new SolidBrush(Color.Black), (AxisZeroPt.X - tmF.Width - ), (AxisZeroPt.Y - YScaleWidth * k - tmF.Height / + ));
- if (k == YSplitNum - )
- {
- tmYvalue = (YScale_StartValue + (k + ) * YScale_SplitValue).ToString();
- tmF = g.MeasureString(tmYvalue, new Font("宋体", ));
- g.DrawString(tmYvalue, new Font("宋体", ), new SolidBrush(Color.Black), (AxisZeroPt.X - tmF.Width - ), (AxisZeroPt.Y - YScaleWidth * (k + ) - tmF.Height / + ));
- }
- }
- // 3.4、绘制网格线
- if (ShowGrid)
- {
- for (int k = ; k <= YSplitNum; k++) // 绘制X轴平行横向辅助线
- g.DrawLine(pen, AxisZeroPt.X + , (AxisZeroPt.Y - YScaleWidth * k), End_X, (AxisZeroPt.Y - YScaleWidth * k));
- for (int k = ; k <= XSplitNum; k++) // 绘制Y轴平行纵向辅助线
- g.DrawLine(pen, (AxisZeroPt.X + XScaleWidth * k), Start_Y, (AxisZeroPt.X + XScaleWidth * k), AxisZeroPt.Y - );
- }
- pen2.Dispose();
- }
- /// <summary>
- /// 绘制曲线图
- /// </summary>
- private void DrawChart_Curve()
- {
- g.SmoothingMode = SmoothingMode.HighQuality;
- g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
- g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
- int tmLength = ;
- PointF[] CurvePointF = new PointF[tmLength];
- foreach (EChartData iItem in this.ChartDataArray)
- {
- tmLength = iItem.Values.Count;
- CurvePointF = new PointF[tmLength];
- pen = new Pen(iItem.ItemColor, 2.0f);
- for (int rr = ; rr < iItem.Values.Count; rr++)
- {
- double dbValue = iItem.Values[rr];
- CurvePointF[rr].X = AxisZeroPt.X + XScaleWidth * rr + XScaleWidth / ;
- CurvePointF[rr].Y = AxisZeroPt.Y - (float)((dbValue - YScale_StartValue) / YScale_SplitValue) * YScaleWidth;
- }
- // 绘制曲线
- g.DrawCurve(pen, CurvePointF, LineTension);
- // 绘制辅点
- for (int tt = ; tt < CurvePointF.Length; tt++)
- {
- // 点标数据值
- string tmValStr = iItem.Values[tt].ToString();
- // 绘制数据点
- g.FillEllipse(new SolidBrush(iItem.ItemColor), CurvePointF[tt].X - , CurvePointF[tt].Y - , , );
- // 绘制数据值
- SizeF tmValueSize = g.MeasureString(tmValStr, new Font("Arial", ));
- g.DrawString(tmValStr, new Font("Arial", ), new SolidBrush(iItem.ItemColor), (CurvePointF[tt].X - tmValueSize.Width / ), (CurvePointF[tt].Y - tmValueSize.Height - 2f));
- }
- }
- }
- /// <summary>
- /// 绘制柱状图
- /// </summary>
- private void DrawChart_Bar()
- {
- g.SmoothingMode = SmoothingMode.HighQuality;
- int tmLen = ChartDataArray.Count; // 柱形条目总数
- float tmBarWidth = XScaleWidth / (tmLen * + ); // 每条柱形宽度 平均分配
- if (tmBarWidth < )
- {
- tmBarWidth = 2f;
- }
- for (int kk = ; kk < this.ChartDataArray.Count; kk++)
- {
- EChartData iItem = this.ChartDataArray[kk];
- pen = new Pen(Color.FromKnownColor(KnownColor.ControlDark), 1.0f);
- for (int rr = ; rr < iItem.Values.Count; rr++)
- {
- RectangleF barRect = new RectangleF(, , , );
- double dbValue = iItem.Values[rr];
- barRect.X = AxisZeroPt.X + XScaleWidth * rr + (tmBarWidth * ((kk + ) * - ));
- barRect.Y = AxisZeroPt.Y - (float)((dbValue - YScale_StartValue) / YScale_SplitValue) * YScaleWidth;
- barRect.Width = tmBarWidth;
- barRect.Height = AxisZeroPt.Y - barRect.Y;
- // 绘制柱形
- g.DrawRectangle(pen, barRect.X, barRect.Y, barRect.Width, barRect.Height);
- brush = new SolidBrush(iItem.ItemColor);
- g.FillRectangle(brush, barRect.X + , barRect.Y + , barRect.Width - , barRect.Height - );
- // 绘制数据
- SizeF tmValueSize = g.MeasureString(dbValue.ToString(), new Font("Arial", ));
- g.DrawString(dbValue.ToString(), new Font("Arial", ), new SolidBrush(iItem.ItemColor), (barRect.X + tmBarWidth / - tmValueSize.Width / ), (barRect.Y - tmValueSize.Height - 2f));
- }
- }
- }
- /// <summary>
- /// 绘制图表--绘制饼状图
- /// </summary>
- private void DrawChart_Pie()
- {
- // 上下预留20 PX 为了标记饼图的数据值
- Start_Y += ;
- End_Y -= ;
- g.SmoothingMode = SmoothingMode.HighQuality;
- g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
- g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
- // 矩形坐标点
- PointF piePoint = new PointF(, );
- float tmPieW = End_X - Start_X;
- float tmPieH = End_Y - Start_Y;
- float tmPieR = tmPieW < tmPieH ? tmPieW / : tmPieH / ; // 半径
- piePoint.X = Start_X + tmPieW / - tmPieR;
- piePoint.Y = Start_Y + tmPieH / - tmPieR;
- // 圆心坐标点
- PointF pieZero = new PointF(piePoint.X + tmPieR, piePoint.Y + tmPieR);
- // 绘制外围圆
- pen = new Pen(Color.FromKnownColor(KnownColor.ControlDark), 1.5f);
- g.DrawEllipse(pen, piePoint.X - , piePoint.Y - , (tmPieR + ) * , (tmPieR + ) * );
- // 计算总数
- double pieCountValue = ;
- foreach (EChartData iItem in this.ChartDataArray)
- {
- if (iItem.Values.Count >= )
- pieCountValue += iItem.Values[];
- }
- // 绘制扇形
- if (pieCountValue > )
- {
- float curAngle = ; // 占比角度
- float sumAngle = ; // 总角度和
- foreach (EChartData iItem in this.ChartDataArray)
- {
- if (iItem.Values.Count >= )
- curAngle = (float)(iItem.Values[] / pieCountValue * );
- else
- curAngle = ;
- // 填充笔刷
- brush = new SolidBrush(iItem.ItemColor);
- // 绘制弧形
- g.FillPie(brush, piePoint.X, piePoint.Y, tmPieR * , tmPieR * , sumAngle, curAngle);
- // 绘制弧线
- g.DrawPie(pen, piePoint.X, piePoint.Y, tmPieR * , tmPieR * , sumAngle, curAngle);
- // 绘制数据
- float tmPre = (float)Math.Round((iItem.Values[] / pieCountValue) * , );
- string tmStr = tmPre.ToString() + "%" + " [" + iItem.Values[].ToString() + "]";
- // 内圆信息
- double relCur_X = tmPieR * Math.Cos(( - sumAngle - curAngle / ) * Math.PI / );
- double relCur_Y = tmPieR * Math.Sin(( - sumAngle - curAngle / ) * Math.PI / );
- double cur_X = relCur_X + pieZero.X;
- double cur_Y = pieZero.Y - relCur_Y;
- PointF cur_Point = new PointF((float)cur_X, (float)cur_Y); // 内圆上弧线中间点的坐标
- // 外圆信息
- float largerR = tmPieR + ;
- double relLarg_X = largerR * Math.Cos(( - sumAngle - curAngle / ) * Math.PI / );
- double relLarg_Y = largerR * Math.Sin(( - sumAngle - curAngle / ) * Math.PI / );
- double largerX = relLarg_X + pieZero.X;
- double largerY = pieZero.Y - relLarg_Y;
- PointF larger_Point = new PointF((float)largerX, (float)largerY);
- SizeF calcSize = new SizeF(, );
- // 绘制链接斜线(内圆到外圆弧度中间点的连接线)
- g.DrawLine(new Pen(new SolidBrush(iItem.ItemColor), 1.5f), cur_Point, larger_Point); // 斜线
- // 绘制横向线条
- //*以下是对四个象限、以及对90度、180度、270度和360度的判断*//
- float tmCurIf = sumAngle + curAngle / ;
- if (tmCurIf <= )
- {
- g.DrawLine(new Pen(new SolidBrush(iItem.ItemColor), 1.5f), larger_Point.X, larger_Point.Y, larger_Point.X + 15f, larger_Point.Y); // 横线
- g.DrawString(tmStr, new Font("Arial", ), new SolidBrush(iItem.ItemColor), larger_Point.X + 15f, larger_Point.Y - 8f); // 文字
- }
- else if (tmCurIf > && tmCurIf <= )
- {
- calcSize = g.MeasureString(tmStr, new Font("Arial", ));
- g.DrawLine(new Pen(new SolidBrush(iItem.ItemColor), 1.5f), larger_Point.X, larger_Point.Y, larger_Point.X - 15f, larger_Point.Y); // 横线
- g.DrawString(tmStr, new Font("Arial", ), new SolidBrush(iItem.ItemColor), larger_Point.X - 15f - calcSize.Width, larger_Point.Y - 8f); // 文字
- }
- else if (tmCurIf > && tmCurIf <= )
- {
- calcSize = g.MeasureString(tmStr, new Font("Arial", ));
- g.DrawLine(new Pen(new SolidBrush(iItem.ItemColor), 1.5f), larger_Point.X, larger_Point.Y, larger_Point.X - 15f, larger_Point.Y); // 横线
- g.DrawString(tmStr, new Font("Arial", ), new SolidBrush(iItem.ItemColor), larger_Point.X - 15f - calcSize.Width, larger_Point.Y - 8f); // 文字
- }
- else
- {
- g.DrawLine(new Pen(new SolidBrush(iItem.ItemColor), 1.5f), larger_Point.X, larger_Point.Y, larger_Point.X + 15f, larger_Point.Y); // 横线
- g.DrawString(tmStr, new Font("Arial", ), new SolidBrush(iItem.ItemColor), larger_Point.X + 15f, larger_Point.Y - 8f); // 文字
- }
- ////*以下是对四个象限、以及对90度、180度、270度和360度的判断*//
- //if ((sumAngle + curAngle / 2) < 90)
- //{
- // Half = sumAngle + curAngle / 2;
- // double tem_sin = Math.Sin(Pi / 180 * Half);
- // double tem_cos = Math.Cos(Pi / 180 * Half);
- // //Math.PI
- // float Px = (float)(tmPieR * tem_cos);
- // float Py = (float)(tmPieR * tem_sin);
- // g.DrawString(tmStr, new Font("Arial", 9), new SolidBrush(Color.Black), piePoint.X + tmPieR + Px, piePoint.Y + Py);
- // //g.DrawString(arraylist_type[i].ToString(), font1, brush1, new Point(225 + x, 225 + y));
- // //g.DrawString((Convert.ToInt32(arraylist_tp[i])).ToString() + "%", font1, brush1, new Point(225 + x, 225 + y + 12));
- //}
- //else if (tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 == 90)
- //{
- // g.DrawString(arraylist_type[i].ToString(), font1, brush1, new Point(225, 225 + 125));
- // g.DrawString((Convert.ToInt32(arraylist_tp[i])).ToString() + "%", font1, brush1, new Point(225, 225 + 125 + 12));
- //}
- //else if (tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 > 90 && tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 < 180)
- //{
- // halfangle = (180 - tem_angle - Convert.ToSingle(arraylist_angle[i]) / 2);
- // double tem_sin = Math.Sin(T / 180 * halfangle);
- // double tem_cos = Math.Cos(T / 180 * halfangle);
- // int y = Convert.ToInt32(125 * tem_sin);
- // int x = Convert.ToInt32(125 * tem_cos);
- // g.DrawString(arraylist_type[i].ToString(), font1, brush1, new Point(225 - x, 225 + y));
- // g.DrawString((Convert.ToInt32(arraylist_tp[i])).ToString() + "%", font1, brush1, new Point(225 - x, 225 + y + 12));
- //}
- //else if (tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 == 180)
- //{
- // g.DrawString(arraylist_type[i].ToString(), font1, brush1, new Point(225 - 125, 225));
- // g.DrawString((Convert.ToInt32(arraylist_tp[i])).ToString() + "%", font1, brush1, new Point(225 - 125, 225 + 12));
- //}
- //else if (tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 > 180 && tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 < 270)
- //{
- // halfangle = (tem_angle - 180 + Convert.ToSingle(arraylist_angle[i]) / 2);
- // double tem_sin = Math.Sin(T / 180 * halfangle);
- // double tem_cos = Math.Cos(T / 180 * halfangle);
- // int y = Convert.ToInt32(125 * tem_sin);
- // int x = Convert.ToInt32(125 * tem_cos);
- // g.DrawString(arraylist_type[i].ToString(), font1, brush1, new Point(225 - x, 225 - y));
- // g.DrawString((Convert.ToInt32(arraylist_tp[i])).ToString() + "%", font1, brush1, new Point(225 - x, 225 - y + 12));
- //}
- //else if (tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 == 270)
- //{
- // g.DrawString(arraylist_type[i].ToString(), font1, brush1, new Point(225, 225 - 125));
- // g.DrawString((Convert.ToInt32(arraylist_tp[i])).ToString() + "%", font1, brush1, new Point(225, 225 - 125 + 12));
- //}
- //else if (tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 > 270 && tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 < 360)
- //{
- // halfangle = (360 - tem_angle - Convert.ToSingle(arraylist_angle[i]) / 2);
- // double tem_sin = Math.Sin(T / 180 * halfangle);
- // double tem_cos = Math.Cos(T / 180 * halfangle);
- // int y = Convert.ToInt32(125 * tem_sin);
- // int x = Convert.ToInt32(125 * tem_cos);
- // g.DrawString(arraylist_type[i].ToString(), font1, brush1, new Point(225 + x, 225 - y));
- // g.DrawString((Convert.ToInt32(arraylist_tp[i])).ToString() + "%", font1, brush1, new Point(225 + x, 225 - y + 12));
- //}
- //else if (tem_angle + Convert.ToSingle(arraylist_angle[i]) / 2 == 360)
- //{
- // g.DrawString(arraylist_type[i].ToString(), font1, brush1, new Point(225 + 125, 225));
- // g.DrawString((Convert.ToInt32(arraylist_tp[i])).ToString() + "%", font1, brush1, new Point(225 + 125, 225 + 12));
- //}
- // 累加角度
- sumAngle += curAngle;
- }
- }
- }
- #endregion
- #region 辅助方法
- /// <summary>
- /// 计算X轴刻度值最大高度
- /// </summary>
- /// <returns></returns>
- private void Calc_XScaleHeight()
- {
- SizeF tmMaxSizeF = new SizeF(, );
- for (int t = ; t < XScaleValues.Count; t++)
- {
- SizeF tmSizeF = g.MeasureString(XScaleValues[t], new Font("宋体", ));
- if (tmSizeF.Width > tmMaxSizeF.Width)
- {
- tmMaxSizeF.Width = tmSizeF.Width;
- tmMaxSizeF.Height = tmSizeF.Height;
- }
- }
- myXScaleMaxHeight = (((float)Math.Sqrt(tmMaxSizeF.Height * tmMaxSizeF.Height + tmMaxSizeF.Width * tmMaxSizeF.Width) - tmMaxSizeF.Height) * XRotateAngle / + tmMaxSizeF.Height + 13f);
- }
- /// <summary>
- /// 计算坐标Y轴的刻度值
- /// 适用于:曲线图、柱状图
- /// 不适用:饼状图无需计算
- /// </summary>
- private void Calc_YScaleValue()
- {
- myMaxValue = ; // 原始最大值
- myMinValue = ; // 原始最小值
- // 计算所有数据的最大值和最小值
- for (int mm = ; mm < this.ChartDataArray.Count; mm++)
- {
- for (int nn = ; nn < this.ChartDataArray[mm].Values.Count; nn++)
- {
- double iData = this.ChartDataArray[mm].Values[nn];
- if (mm == && nn == )
- {
- myMaxValue = iData;
- myMinValue = iData;
- }
- else
- {
- myMaxValue = iData > myMaxValue ? iData : myMaxValue;
- myMinValue = iData > myMinValue ? myMinValue : iData;
- }
- }
- }
- // 计算Y轴刻度
- double tmMax_New = Math.Ceiling(myMaxValue); // 目标最大值 向上取整
- double tmMin_New = Math.Floor(myMinValue); // 目标最小值 向下取整
- if (myMinValue == )
- {
- YScale_SplitValue = Math.Ceiling(tmMax_New / (double)YSplitNum); // 计算Y轴刻度间隔值
- YScale_StartValue = ; // 计算Y轴刻度开始值
- }
- else
- {
- // 计算间隔值
- double tmJD1 = Math.Ceiling((tmMax_New - tmMin_New) / (double)(YSplitNum));
- double tmJD2 = tmJD1 - Math.Ceiling((tmMax_New - tmMin_New) / (double)(YSplitNum + ));
- if (tmJD1 == ) tmJD1 = ;
- YScale_StartValue = tmJD1 * Math.Floor(tmMin_New / tmJD1); // 计算Y轴刻度开始值
- bool tmJDFlag = true;
- while (tmJDFlag)
- {
- if (YScale_StartValue <= tmMin_New && (YScale_StartValue + tmJD1 * YSplitNum) >= tmMax_New)
- {
- tmJDFlag = false;
- YScale_SplitValue = tmJD1; // 计算Y轴刻度间隔值
- break;
- }
- else
- {
- tmJD1 += tmJD2;
- }
- }
- }
- // 计算Y轴刻度字符串的最大宽度
- SizeF tmYSizeF = g.MeasureString((YScale_StartValue + YScale_SplitValue * YSplitNum).ToString(), new Font("宋体", ));
- myYScaleMaxWidth = tmYSizeF.Width + 9f;// 预留4个像素
- }
- #endregion
- #region 枚举方法
- /// <summary>
- /// 枚举图表类型
- /// </summary>
- public enum EChartType
- {
- /// <summary>
- /// 曲线图
- /// </summary>
- Curve,
- /// <summary>
- /// 柱状图
- /// </summary>
- Bar,
- /// <summary>
- /// 饼状图
- /// </summary>
- Pie
- }
- /// <summary>
- /// 枚举对齐方式
- /// </summary>
- public enum EAlign
- {
- /// <summary>
- /// 居左
- /// </summary>
- left,
- /// <summary>
- /// 居中
- /// </summary>
- center,
- /// <summary>
- /// 居右
- /// </summary>
- right
- }
- #endregion
- }
- /// <summary>
- /// 图表数据单个项目
- /// </summary>
- public class EChartData
- {
- private string _name;
- private List<double> _values;
- private Color _itemColor;
- private SizeF _nameSize;
- public EChartData()
- {
- _name = "";
- _values = new List<double>();
- _itemColor = Color.White;
- _nameSize = new SizeF(, );
- }
- /// <summary>
- /// 项目名称
- /// </summary>
- public string Name
- {
- get { return _name; }
- set { _name = value; }
- }
- /// <summary>
- /// 项目值数组
- /// </summary>
- public List<double> Values
- {
- get { return _values; }
- set { _values = value; }
- }
- /// <summary>
- /// 文字大小
- /// 用户绘制图例时候使用
- /// </summary>
- public SizeF NameSize
- {
- get { return _nameSize; }
- set { _nameSize = value; }
- }
- /// <summary>
- /// 项目颜色
- /// </summary>
- public Color ItemColor
- {
- get { return _itemColor; }
- set { _itemColor = value; }
- }
- }
- }
表报设计DLL控件的源码实在太多,这里就不再一一贴出来了,下载完整的源码自己调试运行查看。
此报表设计器结合上次的WEB打印控件,就组成了完整的报表设计。
报表设计器实例完整源码下载地址:www.sdpsoft.com/==》下载中心==》报表设计器简易源码----自定义报表控件(源码)以及在Winform中的使用源码
或直接下载地址:winform报表设计工具源码
欢迎广大朋友一起交流。
C# 报表设计器 (winform 设计端)开发与实现生成网页的HTML报表的更多相关文章
- Web在线报表设计器使用指南
市面上的报表工具有很多,虽说功能大同小异,但每一个报表工具都有各自明确的定位,选择最合适的工具,才能达到事半功倍的效果. 本文将要介绍的ActiveReports报表工具,可全面满足 .NET 报表开 ...
- 解析大型.NET ERP系统核心组件 查询设计器 报表设计器 窗体设计器 工作流设计器 任务计划设计器
企业管理软件包含一些公共的组件,这些基础的组件在每个新项目立项阶段就必须考虑.核心的稳定不变功能,方便系统开发与维护,也为系统二次开发提供了诸多便利.比如通用权限管理系统,通用附件管理,通用查询等组件 ...
- 创建您的 ActiveReports Web端在线报表设计器
概述 ActiveReports Web端在线报表设计器已经正式上线!看到它这么帅气.实用,你是不是也想自己动手创建一个? 现在我们就来教您,如何创建一个简单的 ActiveReports Web端在 ...
- Java开发报表——Grid++Report 报表设计器
为了让数据显示的更加形象生动,报表在项目中差点儿是很常见的,可是大致能够分为两类: 一,图形:以图形的形式显示数据,比如柱状图,折线图,饼形图等等,这里有许多关于这方面的工具,比如JFreeChart ...
- 如何在CRM系统中集成ActiveReports最终报表设计器
有时候,将ActiveReports设计器集成到业务系统中,为用户提供一些自定义的数据表,用户不需要了解如何底层的逻辑关系和后台代码,只需要选择几张关联的数据表,我们会根据用户的选择生成可供用户直接使 ...
- BIRT使用1:简介、概念、元素、报表设计器组成
前一篇博客对birt进行了一个初探,相信通过上篇博客大家对birt有个初步认识,接下来我们随着下面这张思维导图的展示,进入birt的使用学习. 这一篇博客是第一部分,主要介绍一下birt的简介.概念. ...
- 在网页中编辑报表的报表设计器Stimulsoft Reports Designer.Web报表控件
Stimulsoft Reports Designer.Web报表控件是一款网页报表设计器.您想在网页中编辑您的报表吗?现在是可能的! Stimulsoft Reports Designer.Web ...
- 机房收费系统中的Grid++Report报表设计器的应用
在进行账单查询功能的时候我应用了Grid++Report报表设计器,下面我就为大家介绍一下,还望大家多多指点. 首先,在Grid++Report报表设计器中进行报表界面的设置.在属性编辑窗口中这里对报 ...
- H3BPM表单设计器公式设计参考
表单设计器公式设计参考 整体说明 Ø 公式以javascript方式解析,最终支持JS语法或计算方式: Ø 公式变量以数据项为主,以{}符号表示数据项,例如数据项A,表示为{A}:如果是子表中的数据项 ...
随机推荐
- android 手机屏幕有关的几个工具(屏幕宽高,dp和px互相转换)
平时适配页面时经常会需要根据屏幕的宽高来设置控件的大小,很多时候在代码中还会需要dp和px互相转换. 今天把最常用的几个记录一下,经测试包括2.3 ~ 5.0之间的版本都可用,其他版本未测,不过应该也 ...
- 关于MVC中Start.cs文件的作用
当我们建立默认的 .NET Framework4.5.2框架下的Web MVC 应用程序后,调试过程中我发现在程序启动页面加载完成会执行一段代码,这段代码让人有点摸不着头脑,因为之前完全没见过,调试 ...
- 八皇后—Java
package queen; public class queen { static boolean col[] = new boolean[8]; static boolean main_diago ...
- 【Gerrit】Gerrit cmd query (gerrit命令行查询change信息)
本文仅展现个人使用情况和理解,英文原址:https://review.openstack.org/Documentation/cmd-query.html 基本使用格式: ssh -p <por ...
- Exynos 4412
Exynos 4412采用了三星最新的32nm HKMG工艺,是三星的第一款四核处理器 1.启动 有时间再接着写……
- 关于js代码中与或运算符||&&的妙用
看bootstrap时看到如下一行JavaScript代码产生了疑惑. return window.pageYOffset || e.scrollTop ||在这里的作用是什么呢? 首先明确概念,在j ...
- 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 ...
- 各种模板(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 ...
- cf 732c
/* cf732c 错过的最少次数 _________________________________________________________________________________ ...
- EXCEL导入(反射)
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import ja ...