在前面的一些随笔中,介绍了不少我的Winform框架的特性,上篇随笔《Winform开发框架之通用高级查询模块》对其中的通用高级模块进了一个整理说明,本篇继续介绍Winform开发框架重要的一个特性之统计图表的实现。统计图表在很多项目都可能用到,集成到框架中,更方便大家对一些图表项目的设计理解以及功能的重用。在一般的传统的框架中,可以采用ZedGraph开源控件或者微软自带的MSChart进行图表设计,DevExpress控件套件有自己的图表控件,本篇主要介绍基于DevExpress控件的图表控件进行图表设计,进一步丰富我的Winform开发框架。

1、普通统计图表模块

这里指的普通统计图表,只是对表某一项目进行单一的统计,可以从饼状图、柱状图的图表中体现这些项目各自所占的比例和数值,在我的普通统计图表模块中,包括了饼状图、柱状图和数据表格,这样更方便对数据进行全面的分析和查看。整个模块是可以重用的,除了制定字段属性就可以比较合理的展现出不同分类项目的统计效果了,具体效果图如下所示。

上面的统计图表中,还包含了下面两个功能模块,如下所示。

通过以上饼图、柱状图以及数据报表,我们可以很清晰地看到各种统计项目的数值和整体直观的展现图表了。

由于对这类型的图表进行了自定义控件的封装,因此调用非常方便,调用代码如下所示。

1)绑定统计树形列表

为了给用户展示框架(或者项目)支持的报表项目,我们需要在左边的树形列表中初始化一些报表项目,具体代码如下所示。

  1. #region 备件信息统计
  2. this.treeItemDetail.Nodes.Clear();
  3. TreeNode node;
  4.  
  5. node = new TreeNode("备件属类统计", , );
  6. node.Tag = "ItemBigType";
  7. this.treeItemDetail.Nodes.Add(node);
  8.  
  9. node = new TreeNode("备件类别统计", , );
  10. node.Tag = "ItemType";
  11. this.treeItemDetail.Nodes.Add(node);
  12.  
  13. node = new TreeNode("备件材质统计", , );
  14. node.Tag = "Material";
  15. this.treeItemDetail.Nodes.Add(node);
  16.  
  17. node = new TreeNode("备件名称统计", , );
  18. node.Tag = "ItemName";
  19. this.treeItemDetail.Nodes.Add(node);
  20.  
  21. node = new TreeNode("所属库房统计", , );
  22. node.Tag = "WareHouse";
  23. this.treeItemDetail.Nodes.Add(node);
  24.  
  25. node = new TreeNode("所属部门统计", , );
  26. node.Tag = "Dept";
  27. this.treeItemDetail.Nodes.Add(node);
  28.  
  29. //自定义输入字段统计
  30. node = new TreeNode("备件数据动态统计", , );
  31. node.Tag = "Customed";
  32. this.treeItemDetail.Nodes.Add(node);
  33.  
  34. #endregion

上面的树形列表中,我们给Tag赋值,一般情况下是表字段的名称,有些特殊的,则采用Customed来表示,我们响应树形列表控件的操作,根据Tag的不同,切换到不同的报表自定义控件进行展现(包括自定义动态项目统计图表和普通统计图表项目)。

由于我们对图表的展现进行了比较合理的封装,因此基本上普通的图表统计项目,只是字段名称的不同。

对于普通统计图表项目FrmCategoryReport,这个是一个自定义控件来的,方便动态加载到右边的展示Panel区域,这样我们就能根据不同类型的报表动态加载。

创建图表的代码如下所示。

  1. private DataTable dt = null;
  2. private void BindData()
  3. {
  4. if (string.IsNullOrEmpty(FieldName)) return;
  5.  
  6. //设置报表标题
  7. this.Text = ReportTitle;
  8. this.lblReportTitle.Text = ReportTitle;
  9.  
  10. this.chartPie.Series.Clear();
  11. this.chartBar.Series.Clear();
  12.  
  13. string where = GetConditionSql();
  14. dt = BLLFactory<ItemDetail>.Instance.GetReportData(FieldName, where);
  15.  
  16. this.gridControl1.DataSource = dt;
  17.  
  18. if (dt != null && dt.Rows.Count > )
  19. {
  20. this.chartPie.DataSource = dt;
  21.  
  22. Series pieSeries = CreateSeries(dt, DevExpress.XtraCharts.ViewType.Pie3D, NumericFormat.Percent);
  23. chartPie.Series.Add(pieSeries);
  24. chartPie.Legend.Visible = true;
  25.  
  26. PieSeriesLabel label = pieSeries.Label as PieSeriesLabel;
  27. ((PiePointOptions)label.PointOptions).PercentOptions.PercentageAccuracy = ;
  28. ((PiePointOptions)label.PointOptions).PercentOptions.ValueAsPercent = true;
  29.  
  30. label.Position = PieSeriesLabelPosition.TwoColumns; //设置饼图上lable的显示方式,此方式将独立出一个列显示lable
  31. (pieSeries.View as DevExpress.XtraCharts.Pie3DSeriesView).ExplodeMode = PieExplodeMode.All; //突出显示饼块
  32. (pieSeries.View as DevExpress.XtraCharts.Pie3DSeriesView).ExplodedDistancePercentage = ;
  33. //(pieSeries.View as DevExpress.XtraCharts.PieSeriesView).RuntimeExploding = true; //设置了他,你就可以把你喜欢的饼块拖出来。。。
  34.  
  35. this.chartBar.DataSource = dt;
  36. chartBar.Series.Add(CreateSeries(dt, DevExpress.XtraCharts.ViewType.Bar, NumericFormat.General));
  37. chartBar.Legend.Visible = false;
  38. chartBar.SeriesTemplate.LabelsVisibility = DefaultBoolean.True;
  39. }
  40.  
  41. this.xtraTabControl1.SelectedTabPageIndex = ;
  42. }

其中我们注意到,创建图表的Series对象的方法,我进行了进一步的封装。

  1. Series pieSeries = CreateSeries(dt, DevExpress.XtraCharts.ViewType.Pie3D, NumericFormat.Percent);

其中CreateSeries方法代码如下所示。

  1. /// <summary>
  2. /// 创建图表的Series对象,可以指定相应的类型
  3. /// </summary>
  4. /// <param name="dt">数据源</param>
  5. /// <param name="viewType">图表类型,如DevExpress.XtraCharts.ViewType.Pie3D,DevExpress.XtraCharts.ViewType.Bar</param>
  6. /// <param name="format">显示格式,如百分比NumericFormat.Percent,NumericFormat.General</param>
  7. /// <returns></returns>
  8. private Series CreateSeries(DataTable dt, DevExpress.XtraCharts.ViewType viewType, NumericFormat format)
  9. {
  10. Series series = new Series("Serices1 ", viewType);
  11. series.DataSource = dt;
  12. series.ArgumentScaleType = ScaleType.Qualitative;
  13. series.ArgumentDataMember = "argument";
  14. series.ValueScaleType = ScaleType.Numerical;
  15. series.ValueDataMembers.AddRange(new string[] { "datavalue" });
  16. series.PointOptions.PointView = PointView.ArgumentAndValues;
  17. series.PointOptions.ValueNumericOptions.Format = format;
  18. if (format == NumericFormat.Number)
  19. {
  20. //series.PointOptions.ValueNumericOptions.Precision = 0;
  21. }
  22.  
  23. series.LabelsVisibility = DevExpress.Utils.DefaultBoolean.True;//显示标注标签
  24.  
  25. return series;
  26. }

在Winform开发框架中,我试图对备件仓库中不同类型的设备进行一个库存统计,也得到了这类型的图表如下所示。

2、动态项目统计图表模块

有时候,我们对于表里面的数据,可能要对不同类型的内容进行动态的统计,以确定他们各自的比例情况,那么这些动态项目的统计图表就比较合适了,例如,对于病人资料的管理,我们可能需要统计各种病种所占的比例或者各种职业类型的犯病率,这些不太确定的统计项目,就需要一个能够支持动态项目的统计图表进行支撑,对于本Winform框架,为了较好呈现这个类型报表的意义,我选择了对备件类型所占的比例进行一个统计分析,得到下面的统计图表,如下所示。

上面的图表统计,除了能够根据一些条件进行限定查询范围外,还可以对一些预设的统计字段进行动态选取,然后根据字段里面的各种内容(统计项目)进行统计,这样就可以比较有效的统计出各种类型的数值和比例了。

动态项目的统计,主要是对不同字段,以及对应不同字段的内容进行一个条件分析,把它们的统计数字构造一个数据表格即可进行合理展现,如下部门代码所示。

  1. string fieldName = fieldItem.Value;
  2. int totalCount = BLLFactory<ItemDetail>.Instance.GetRecordCount(where);//计算总人数
  3. foreach (string searchItem in this.lstItems.Items)
  4. {
  5. string condition = string.Format("{0} like '%{1}%' ", fieldName, searchItem);
  6. if (!string.IsNullOrEmpty(where))
  7. {
  8. condition += string.Format(" AND {0}", where);
  9. }
  10.  
  11. int countValue = BLLFactory<ItemDetail>.Instance.GetRecordCount(condition);//计算总人数
  12. countRepeat += countValue;
  13.  
  14. row = dt.NewRow();
  15. row[] = searchItem;
  16. row[] = countValue;
  17. dt.Rows.Add(row);
  18. }

3、多重坐标对比统计图表模块

有时候我们可能需要对某年各个月份的数值进行对比统计,已看出各种统计项目的发展趋势或者对比效果,这就要求可以对多份数据进行合并展现,这种在图表展现中可以使用多重坐标对比的统计图表模块进行展现,如我上篇随笔《DevExpress控件使用之多重坐标图形的绘制》就对这类型的图表统计进行了比较细致的分析和说明,相关的效果图如下所示。

在Winform框架里面,可以对某一年各月份的出入库数量进行一个分析,得到下面的统计图。

以上数据不多,展现可能不太好看,下面我给出我另一个软件系统的界面,其中对病人的出入院记录进行一个统计对比分析,统计报表如下所示。

4、打印及导出报表

很多时候,我们可能需要对呈现的报表进行一个打印和导出操作,对于DevExpress的ChartControl控件,打印操作很简单,你甚至可以用一行代码进行打印操作。

  1. this.chartControl1.ShowPrintPreview(DevExpress.XtraCharts.Printing.PrintSizeMode.Zoom);

或者增加更复杂的定制操作,代码如下所示。

  1. private void btnPrint_Click(object sender, EventArgs e)
  2. {
  3. //this.chartControl1.ShowPrintPreview(DevExpress.XtraCharts.Printing.PrintSizeMode.Zoom);
  4. DevExpress.XtraPrintingLinks.CompositeLink compositeLink = new DevExpress.XtraPrintingLinks.CompositeLink();
  5. DevExpress.XtraPrinting.PrintingSystem ps = new DevExpress.XtraPrinting.PrintingSystem();
  6.  
  7. compositeLink.PrintingSystem = ps;
  8. compositeLink.Landscape = true;
  9. compositeLink.PaperKind = System.Drawing.Printing.PaperKind.A4;
  10.  
  11. DevExpress.XtraPrinting.PrintableComponentLink link = new DevExpress.XtraPrinting.PrintableComponentLink(ps);
  12. ps.PageSettings.Landscape = true;
  13. link.Component = this.chartControl1;
  14. compositeLink.Links.Add(link);
  15.  
  16. link.CreateDocument(); //建立文档
  17. ps.PreviewFormEx.Show();//进行预览
  18. }

对于导出报表,我们 一般要求图文并茂,纯粹导出图表的图片或者列表,都是一件很简单的事情,但是要把它们整合一起,并进行合理的排版,这需要费一点心思才能做好。

首先我们来介绍一下,一般图表控件都有导出Image图片类型的操作,DevExpress控件也不例外,它的操作代码如下所示。

  1. //插入图片到Excel里面
  2. using (MemoryStream stream = new MemoryStream())
  3. {
  4. stream.Position = ;
  5. ChartControl chart = (ChartControl)chartControl1.Clone();
  6. chart.Size = new Size(, );
  7.  
  8. chart.ExportToImage(stream, ImageFormat.Jpeg);
  9. //进行存储操作
  10. //worksheet.Pictures.Add(startRow, 0, stream);
  11. }

为了更好的整合几个图表和数据报表,我们这里采用了Aspose.Cell控件进行代码操作,把这些图表动态整合到一个Excel文档里面进行导出,全部代码如下所示。

  1. private void btnExport_Click(object sender, EventArgs e)
  2. {
  3. try
  4. {
  5. DataTable dt = this.gridControl1.DataSource as DataTable;
  6. if (dt == null || dt.Rows.Count == )
  7. {
  8. MessageDxUtil.ShowTips("没有数据需要导出!");
  9. return;
  10. }
  11.  
  12. string saveDocFile = FileDialogHelper.SaveExcel(string.Format("{0}.xls", ReportTitle), "C:\\");
  13. if (!string.IsNullOrEmpty(saveDocFile))
  14. {
  15. Workbook workbook = new Workbook();
  16. Worksheet worksheet = workbook.Worksheets[];
  17. worksheet.PageSetup.Orientation = PageOrientationType.Landscape;//横向打印
  18. worksheet.PageSetup.Zoom = ;//以100%的缩放模式打开
  19. worksheet.PageSetup.PaperSize = PaperSizeType.PaperA4;
  20.  
  21. #region 表头及说明信息
  22. Range range; Cell cell; string content;
  23. int colSpan = ;
  24. range = worksheet.Cells.CreateRange(, , , colSpan);
  25. range.Merge();
  26. range.RowHeight = ;
  27. range.Style = CreateTitleStyle(workbook);
  28. cell = range[, ];
  29. cell.PutValue(ReportTitle);
  30.  
  31. range = worksheet.Cells.CreateRange(, , , colSpan);
  32. range.Merge();
  33. range.RowHeight = ;
  34. cell = range[, ];
  35. content = string.Format("统计报表详细列表如下:");
  36. cell.PutValue(content);
  37.  
  38. #endregion
  39.  
  40. #region 生成报表头部表格
  41. Style headStyle = CreateStyle(workbook, true);
  42. Style normalStyle = CreateStyle(workbook, false);
  43. int startRow = ;
  44. int startCol = ;
  45.  
  46. int index = ;
  47. foreach (DataColumn col in dt.Columns)
  48. {
  49. range = worksheet.Cells.CreateRange(startRow, index, , );
  50. range.Merge();
  51. range.Style = headStyle;
  52. cell = range[, ];
  53. cell.PutValue(col.ColumnName);
  54. cell.Style = headStyle;
  55. index++;
  56. }
  57.  
  58. #endregion
  59.  
  60. //写入数据到Excel
  61. startRow = startRow + ;
  62. for (int i = ; i < dt.Rows.Count; i++)
  63. {
  64. startCol = ;
  65. for (int j = ; j < dt.Columns.Count; j++)
  66. {
  67. DataRow dr = dt.Rows[i];
  68. cell = worksheet.Cells[startRow, startCol];
  69. cell.PutValue(dr[j]);
  70. cell.Style = normalStyle;
  71.  
  72. startCol++;
  73. }
  74. startRow++;
  75. }
  76.  
  77. //写入图注
  78. startRow += ;//跳过1行
  79. range = worksheet.Cells.CreateRange(startRow++, , , colSpan);
  80. range.Merge();
  81. range.RowHeight = ;
  82. cell = range[, ];
  83. cell.PutValue("以曲线图展示如下:");
  84.  
  85. //插入图片到Excel里面
  86. using (MemoryStream stream = new MemoryStream())
  87. {
  88. stream.Position = ;
  89. ChartControl chart = (ChartControl)chartControl1.Clone();
  90. chart.Size = new Size(, );
  91.  
  92. chart.ExportToImage(stream, ImageFormat.Jpeg);
  93. worksheet.Pictures.Add(startRow, , stream);
  94. }
  95.  
  96. workbook.Save(saveDocFile);
  97. if (MessageUtil.ShowYesNoAndTips("保存成功,是否打开文件?") == System.Windows.Forms.DialogResult.Yes)
  98. {
  99. System.Diagnostics.Process.Start(saveDocFile);
  100. }
  101. }
  102. }
  103. catch (Exception ex)
  104. {
  105. LogTextHelper.Error(ex);
  106. MessageUtil.ShowError(ex.Message);
  107. return;
  108. }
  109. }

导出Excel的效果如下所示。

5、整体Winform开发框架的特点介绍

下面是我对Winform开发框架大的方面的特性进行一个整理,希望能够概括整个框架的一些常用特性,较之前的图形,增加了高级查询模块,统计图表模块等内容。希望大家批评指正。

Winform开发框架之统计图表的实现的更多相关文章

  1. [转载]Winform开发框架之统计图表的实现

    在前面的一些随笔中,介绍了不少我的Winform框架的特性,上篇随笔<Winform开发框架之通用高级查询模块>对其中的通用高级模块进了一个整理说明,本篇继续介绍Winform开发框架重要 ...

  2. Winform开发框架的重要特性总结

    从事Winform开发框架的研究和推广,也做了有几个年头了,从最初的项目雏形到目前各种重要特性的加入完善,是经过了很多项目的总结归纳和升华,有些则是根据客户需要或者应用前景的需要进行的完善,整个Win ...

  3. [转]Winform开发框架的重要特性总结

    本文转自:https://www.cnblogs.com/wuhuacong/p/3199829.html 从事Winform开发框架的研究和推广,也做了有几个年头了,从最初的项目雏形到目前各种重要特 ...

  4. 基于Enterprise Library的Winform开发框架实现支持国产达梦数据库的扩展操作

    由于一个客户朋友的需求,需要我的Winform开发框架支持国产达梦数据库的操作,这个数据库很早就听过,但是真正一般项目用的很少,一般在一些特殊的项目可能需要用到.由于我的Winform开发框架,是基于 ...

  5. Winform开发框架中实现同时兼容多种数据库类型处理

    在很多应用系统里面,虽然一般采用一种数据库运行,但是由于各种情况的需要,可能业务系统会部署在不同类型的数据库上,如果开发的系统能够很方便支持多种数据库的切换,那可以为我们减少很多烦恼,同时提高系统的适 ...

  6. Winform开发框架之存储过程的支持--存储过程的实现和演化提炼(2)

    本篇继续上篇<Winform开发框架之存储过程的支持--存储过程的实现和演化提炼(1)>来对Winform开发框架之存储过程的支持进行介绍,上篇主要介绍了SQLServer和Oracle两 ...

  7. Winform开发框架之读卡器和条码扫描枪的数据接收处理

    在我们开发一些项目的时候,一般需要一些外围的设备进行数据处理,如ID/IC读卡器获取卡号.激光条码扫描枪.USB摄像头.USB方式的小票据打印机(POS打印机).USB来电录音盒.普通打印机等一系列附 ...

  8. Winform开发框架中实现多种数据库类型切换以及分拆数据库的支持

    在很多应用系统里面,虽然一般采用一种数据库运行,但是由于各种情况的需要,可能业务系统会部署在不同类型的数据库上,如果开发的系统能够很方便支持多种数据库的切换,那可以为我们减少很多烦恼,同时提高系统的适 ...

  9. WinForm开发框架--动态读取DLL模式

    1\ WinForm开发框架--动态读取DLL模式   http://www.2cto.com/kf/201306/217199.html 2\ 广州爱奇迪     http://www.iqidi. ...

随机推荐

  1. FEC难:

     飞雨(314698641)  12:03:16 有人研究fec吗把信源编码好信道编码区别开来 ? 杭州桓泽(84894922)  12:52:54fec实际是一种概括性技术可以从信源的方面做fec就 ...

  2. algo_预备

    章 C + +程序设计 大家好!现在我们将要开始一个穿越" 数据结构.算法和程序" 这个抽象世界的特殊旅程,以解决现实生活中的许多难题.在程序开发过程中通常需要做到如下两点:一是高 ...

  3. BusyBox

    http://blog.csdn.net/a345017062/article/details/6250619

  4. iOS CoreData技术学习资源汇总

    一.CoreData学习指引 1. 苹果官方:Core Data Programming Guide 什么是CoreData? 创建托管对象模型 初始化Core Data堆栈 提取对象 创建和修改自定 ...

  5. post 的body json要使用双引号,而不是单引号

      string parse error , JS eval error {'name' : 'wade' }   http://json.parser.online.fr/ string parse ...

  6. hao.360.cn不停跳....

    最近单位里访问hao.360.cn经常会跳....无限循环,有时跳几十次后才会打开.... 但是,单位里走电信出口部分的电脑就没有问题...同样的电脑(移动出口)的用360浏览器.火狐也问题不大,关键 ...

  7. LeetCode: 221_Maximal Square | 二维0-1矩阵中计算包含1的最大正方形的面积 | Medium

    题目: Given a 2D binary matrix filled with 's and return its area. For example, given the following ma ...

  8. iOS 模拟器键盘弹出以及中文输入

    1.虚拟键盘的弹出与收起切换: 快捷键:command+shift+K 2.中文输入: Xcode 菜单项 --> Product --> Scheme --> Edit Schem ...

  9. 重新发现梯度下降法--backtracking line search

    一直以为梯度下降很简单的,结果最近发现我写的一个梯度下降特别慢,后来终于找到原因:step size的选择很关键,有一种叫backtracking line search的梯度下降法就非常高效,该算法 ...

  10. mysql 慢查询日志记录

    环境: 操作系统: CentOS  6.5 数据库:    mysql-5.1.73 1.查看当前慢查询配置 mysql> show variables like 'slow%'; +----- ...