在前面的一些随笔中,介绍了不少我的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. UI1_UINavigationController

    // // FourthViewController.h // UI1_UINavigationController // // Created by zhangxueming on 15/7/6. ...

  2. 13款精彩实用的最新jQuery插件

    1.jQuery特色菜单 圆形动画菜单插件 jQuery是一个非常流行的WEB前端框架,尽管HTML5非常酷,但是如果HTML5结合jQuery的话就能实现更酷更实用的插件.今天分享的这款jQuery ...

  3. IEEE Floating Point Standard (IEEE754浮点数表示法标准)

    浮点数与定点数表示法是我们在计算机中常用的表示方法 所以必须要弄懂原理,特别是在FPGA里面,由于FPGA不能像在MCU一样直接用乘除法. 定点数 首先说一下简单的定点数,定点数是克服整数表示法不能表 ...

  4. js设计模式(8)---享元模式

    0.前言 今天总结了四种设计模式,到现在有点精疲力尽了,但是还是有不少收获,很开心自己有掌握了新的东西,今天变得有了价值. 1.使用条件 1.1.网页中使用了大量资源密集型的对象: 1.2.这些对象中 ...

  5. SQL 面试题(一)

    问题来自于CSDN问答,练练SQL吧. 测试数据SQL代码: if OBJECT_ID('td_ls_2') is not null drop table td_ls_2 go if OBJECT_I ...

  6. UINavigationController 与 UITabBarController

    http://www.cnblogs.com/YouXianMing/p/3756904.html // index start from 1. UITabBarItem *newsItem = [[ ...

  7. canvas 绘点图

    canvas 绘点图 项目中需要一个记录点实时变动的信息,在此记录一下: <!DOCTYPE html> <html lang="en"> <head ...

  8. java 高精度

    package BigDecimal; import java.math.BigDecimal; import java.lang.Object; public class BigDecimalTes ...

  9. 编辑器未包含main类型解决方法

    将文件移到 src 这个 Java Source Folder 下面去,现在在外面的 java 文件不会被当成一个需要编译的类,eclipse 不会编译 Java Source Folder 外面的任 ...

  10. 多线程中,static函数与非static函数的区别?

    最近在学习多线程,刚入门,好多东西不懂,下面这段代码今天想了半天也没明白,希望看到的兄弟姐妹能解释下. public class NotThreadSafeCounter extends Thread ...