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

1、普通统计图表模块

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

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

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

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

1)绑定统计树形列表

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

#region 备件信息统计
this.treeItemDetail.Nodes.Clear();
TreeNode node; node = new TreeNode("备件属类统计", , );
node.Tag = "ItemBigType";
this.treeItemDetail.Nodes.Add(node); node = new TreeNode("备件类别统计", , );
node.Tag = "ItemType";
this.treeItemDetail.Nodes.Add(node); node = new TreeNode("备件材质统计", , );
node.Tag = "Material";
this.treeItemDetail.Nodes.Add(node); node = new TreeNode("备件名称统计", , );
node.Tag = "ItemName";
this.treeItemDetail.Nodes.Add(node); node = new TreeNode("所属库房统计", , );
node.Tag = "WareHouse";
this.treeItemDetail.Nodes.Add(node); node = new TreeNode("所属部门统计", , );
node.Tag = "Dept";
this.treeItemDetail.Nodes.Add(node); //自定义输入字段统计
node = new TreeNode("备件数据动态统计", , );
node.Tag = "Customed";
this.treeItemDetail.Nodes.Add(node); #endregion

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

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

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

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

private DataTable dt = null;
private void BindData()
{
if (string.IsNullOrEmpty(FieldName)) return; //设置报表标题
this.Text = ReportTitle;
this.lblReportTitle.Text = ReportTitle; this.chartPie.Series.Clear();
this.chartBar.Series.Clear(); string where = GetConditionSql();
dt = BLLFactory<ItemDetail>.Instance.GetReportData(FieldName, where); this.gridControl1.DataSource = dt; if (dt != null && dt.Rows.Count > )
{
this.chartPie.DataSource = dt; Series pieSeries = CreateSeries(dt, DevExpress.XtraCharts.ViewType.Pie3D, NumericFormat.Percent);
chartPie.Series.Add(pieSeries);
chartPie.Legend.Visible = true; PieSeriesLabel label = pieSeries.Label as PieSeriesLabel;
((PiePointOptions)label.PointOptions).PercentOptions.PercentageAccuracy = ;
((PiePointOptions)label.PointOptions).PercentOptions.ValueAsPercent = true; label.Position = PieSeriesLabelPosition.TwoColumns; //设置饼图上lable的显示方式,此方式将独立出一个列显示lable
(pieSeries.View as DevExpress.XtraCharts.Pie3DSeriesView).ExplodeMode = PieExplodeMode.All; //突出显示饼块
(pieSeries.View as DevExpress.XtraCharts.Pie3DSeriesView).ExplodedDistancePercentage = ;
//(pieSeries.View as DevExpress.XtraCharts.PieSeriesView).RuntimeExploding = true; //设置了他,你就可以把你喜欢的饼块拖出来。。。 this.chartBar.DataSource = dt;
chartBar.Series.Add(CreateSeries(dt, DevExpress.XtraCharts.ViewType.Bar, NumericFormat.General));
chartBar.Legend.Visible = false;
chartBar.SeriesTemplate.LabelsVisibility = DefaultBoolean.True;
} this.xtraTabControl1.SelectedTabPageIndex = ;
}

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

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

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

/// <summary>
/// 创建图表的Series对象,可以指定相应的类型
/// </summary>
/// <param name="dt">数据源</param>
/// <param name="viewType">图表类型,如DevExpress.XtraCharts.ViewType.Pie3D,DevExpress.XtraCharts.ViewType.Bar</param>
/// <param name="format">显示格式,如百分比NumericFormat.Percent,NumericFormat.General</param>
/// <returns></returns>
private Series CreateSeries(DataTable dt, DevExpress.XtraCharts.ViewType viewType, NumericFormat format)
{
Series series = new Series("Serices1 ", viewType);
series.DataSource = dt;
series.ArgumentScaleType = ScaleType.Qualitative;
series.ArgumentDataMember = "argument";
series.ValueScaleType = ScaleType.Numerical;
series.ValueDataMembers.AddRange(new string[] { "datavalue" });
series.PointOptions.PointView = PointView.ArgumentAndValues;
series.PointOptions.ValueNumericOptions.Format = format;
if (format == NumericFormat.Number)
{
//series.PointOptions.ValueNumericOptions.Precision = 0;
} series.LabelsVisibility = DevExpress.Utils.DefaultBoolean.True;//显示标注标签 return series;
}

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

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

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

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

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

string fieldName = fieldItem.Value;
int totalCount = BLLFactory<ItemDetail>.Instance.GetRecordCount(where);//计算总人数
foreach (string searchItem in this.lstItems.Items)
{
string condition = string.Format("{0} like '%{1}%' ", fieldName, searchItem);
if (!string.IsNullOrEmpty(where))
{
condition += string.Format(" AND {0}", where);
} int countValue = BLLFactory<ItemDetail>.Instance.GetRecordCount(condition);//计算总人数
countRepeat += countValue; row = dt.NewRow();
row[] = searchItem;
row[] = countValue;
dt.Rows.Add(row);
}

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

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

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

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

4、打印及导出报表

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

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

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

private void btnPrint_Click(object sender, EventArgs e)
{
//this.chartControl1.ShowPrintPreview(DevExpress.XtraCharts.Printing.PrintSizeMode.Zoom);
DevExpress.XtraPrintingLinks.CompositeLink compositeLink = new DevExpress.XtraPrintingLinks.CompositeLink();
DevExpress.XtraPrinting.PrintingSystem ps = new DevExpress.XtraPrinting.PrintingSystem(); compositeLink.PrintingSystem = ps;
compositeLink.Landscape = true;
compositeLink.PaperKind = System.Drawing.Printing.PaperKind.A4; DevExpress.XtraPrinting.PrintableComponentLink link = new DevExpress.XtraPrinting.PrintableComponentLink(ps);
ps.PageSettings.Landscape = true;
link.Component = this.chartControl1;
compositeLink.Links.Add(link); link.CreateDocument(); //建立文档
ps.PreviewFormEx.Show();//进行预览
}

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

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

//插入图片到Excel里面
using (MemoryStream stream = new MemoryStream())
{
stream.Position = ;
ChartControl chart = (ChartControl)chartControl1.Clone();
chart.Size = new Size(, ); chart.ExportToImage(stream, ImageFormat.Jpeg);
//进行存储操作
//worksheet.Pictures.Add(startRow, 0, stream);
}

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

private void btnExport_Click(object sender, EventArgs e)
{
try
{
DataTable dt = this.gridControl1.DataSource as DataTable;
if (dt == null || dt.Rows.Count == )
{
MessageDxUtil.ShowTips("没有数据需要导出!");
return;
} string saveDocFile = FileDialogHelper.SaveExcel(string.Format("{0}.xls", ReportTitle), "C:\\");
if (!string.IsNullOrEmpty(saveDocFile))
{
Workbook workbook = new Workbook();
Worksheet worksheet = workbook.Worksheets[];
worksheet.PageSetup.Orientation = PageOrientationType.Landscape;//横向打印
worksheet.PageSetup.Zoom = ;//以100%的缩放模式打开
worksheet.PageSetup.PaperSize = PaperSizeType.PaperA4; #region 表头及说明信息
Range range; Cell cell; string content;
int colSpan = ;
range = worksheet.Cells.CreateRange(, , , colSpan);
range.Merge();
range.RowHeight = ;
range.Style = CreateTitleStyle(workbook);
cell = range[, ];
cell.PutValue(ReportTitle); range = worksheet.Cells.CreateRange(, , , colSpan);
range.Merge();
range.RowHeight = ;
cell = range[, ];
content = string.Format("统计报表详细列表如下:");
cell.PutValue(content); #endregion #region 生成报表头部表格
Style headStyle = CreateStyle(workbook, true);
Style normalStyle = CreateStyle(workbook, false);
int startRow = ;
int startCol = ; int index = ;
foreach (DataColumn col in dt.Columns)
{
range = worksheet.Cells.CreateRange(startRow, index, , );
range.Merge();
range.Style = headStyle;
cell = range[, ];
cell.PutValue(col.ColumnName);
cell.Style = headStyle;
index++;
} #endregion //写入数据到Excel
startRow = startRow + ;
for (int i = ; i < dt.Rows.Count; i++)
{
startCol = ;
for (int j = ; j < dt.Columns.Count; j++)
{
DataRow dr = dt.Rows[i];
cell = worksheet.Cells[startRow, startCol];
cell.PutValue(dr[j]);
cell.Style = normalStyle; startCol++;
}
startRow++;
} //写入图注
startRow += ;//跳过1行
range = worksheet.Cells.CreateRange(startRow++, , , colSpan);
range.Merge();
range.RowHeight = ;
cell = range[, ];
cell.PutValue("以曲线图展示如下:"); //插入图片到Excel里面
using (MemoryStream stream = new MemoryStream())
{
stream.Position = ;
ChartControl chart = (ChartControl)chartControl1.Clone();
chart.Size = new Size(, ); chart.ExportToImage(stream, ImageFormat.Jpeg);
worksheet.Pictures.Add(startRow, , stream);
} workbook.Save(saveDocFile);
if (MessageUtil.ShowYesNoAndTips("保存成功,是否打开文件?") == System.Windows.Forms.DialogResult.Yes)
{
System.Diagnostics.Process.Start(saveDocFile);
}
}
}
catch (Exception ex)
{
LogTextHelper.Error(ex);
MessageUtil.ShowError(ex.Message);
return;
}
}

导出Excel的效果如下所示。

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

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

原文地址:http://www.cnblogs.com/wuhuacong/p/3148677.html

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

  1. Winform开发框架之统计图表的实现

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

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

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

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

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

  4. 在Winform开发框架中实现对数据库的加密支持(转)

    在很多情况下,我们需要对数据库进行加密,特别是Access数据库.Sqlite数据库,这些直接部署在客户端的数据,因为数据也是客户的资产,数据库总是存在很多相关的秘密或者重要的业务数据,所以一般来说, ...

  5. Winform开发框架之通用Windows摄像头调用拍照--SNF快速开发平台3.3-Spring.Net.Framework

    今天做了一个windows系统下调用摄像头.进行开启.关闭.拍照.设置等等功能演示. 进行源码贡献,欢迎大家下载使用 一.DEMO效果如下: 二.DEMO演示代码如下: using SNF.Utili ...

  6. Winform开发框架之图表报表在线设计器2-图表-SNF.EasyQuery项目--SNF快速开发平台3.3-Spring.Net.Framework

    上一篇讲到,如何快速创建报表程序了.这篇教大家如何快速制作图表报表. 继上一篇,Winform开发框架之图表报表在线设计器-报表 上一篇讲到如何了创建数据源,这里就不在介绍了.那我们就直接从图表设计器 ...

  7. Winform开发框架之图表报表在线设计器-报表-SNF.EasyQuery项目--SNF快速开发平台3.3-+Spring.Net.Framework

    带过项目和做过项目的人都知道,在客户现场客户的需求是百般多样的,今天要查销售出库情况,明天要看整个月的各部门销售情况,后天要查全年每个客户的项目金额.一直以前都有新需求,虽然会有售后收益,但如果有一个 ...

  8. Winform开发框架之通用附件管理模块 --SNF快速开发平台3.3-Spring.Net.Framework

    最近项目太多都没有时间写文章了,实际项目需求一,CS端和windows平板都需要附件上传管理功能.以前做的都是BS的附件管理和上传功能.本来计划在Winform上嵌套一个浏览器直接用bs的附件上传功能 ...

  9. Winform开发框架之框架演化

    Winform开发框架方面的文章我介绍很多了,有宏观介绍,也有部分技术细节的交流,每次我希望能从不同角度,不同方面来介绍我的WInform开发框架,这些其实都是来源于客户的需求,真实的项目场景.本文主 ...

随机推荐

  1. oracle生成.net的guid方法;

    最近在做一个T1的.NET项目,数据库oracle的时候,遇到一个问题..NET里面的某个数据库表类的某个字段是guid类型.但是用oracle生成的guid.跟.NET的guid 无法识别.导致报错 ...

  2. C# 线程--第一单线程基础

    概念 什么是进程? 当一个程序被打开运行时,它就是一个进程.在进程中包括线程,进程可以由一个或多个线程组成. 什么是线程? 线程是程序执行流的最小单元.一个标准的线程由线程ID,当前指令指针(PC), ...

  3. 20150226—C# winform中的ListView解析

    ListView在WinForm中多用于表的构建,可以直观的显示表的信息,其格式如同SQL的表 这是他的位置,在公共控件中: Listview的几个重要属性:Columms(集合).Groups(集合 ...

  4. Python的functools.reduce用法

    python 3.0以后, reduce已经不在built-in function里了, 要用它就得from functools import reduce. reduce的用法 reduce(fun ...

  5. 南阳理工oj88--汉诺塔(一)

    题目链接.http://acm.nyist.net/JudgeOnline/problem.php?pid=88 #include <stdio.h> /* //测试一下49999和500 ...

  6. Toad for Oracle 快捷键

    F4 看表的结构 F5 执行对话框中的SQL,注意最后需要以;结尾 F7 清除当前编辑框中所有的sql F8 查看历史的sql语句 F9 执行当前行的sql F10 看菜单 Ctrl + F12 保存 ...

  7. opencv获取图片sift特征

    利用opencv2.3来获取图片的sift特征,并输出到标准输出,可用重定向到文件. #include<cstdio> #include"opencv2/opencv.hpp&q ...

  8. MFC控件随窗口大小变化原理及实现

    本文主要针对MFC的dialog,实现控件随窗口大小变化. 原理:首先获取dialog的初始大小,当窗口发送变动时,调用OnSize事件和方法,计算缩放比例,然后对界面中的所有控件进行缩放和布局. 实 ...

  9. 版本控制器 (Svn,Git)

    Svn: 集中式版本控制器,首先开发者在开始新一天的工作之前必须从服务器获取代码,然后进入自己的分支开发,开发完成后把自己的分支合并到主分支上进行提交,解决冲突.所有的版本信息都放在服务器上.如果脱离 ...

  10. Waring:This LinearLayout layout or its FrameLayout parent is useless; transfer the background attribute to the other view

    解决方法请参考: You have a single component (row) vertical linear layout, containing another linear layout. ...