OWC ChartSpace控件的使用

OWC ChartSpace 控件是微软OWC库中的一种ActiveX控件,主要是用于生成图表。该控件既可以用于服务器端(生成图片),也可以直接嵌入到客户端(Winform或IE)中。说实话,在Asp.net生成图表的方法很多,比如微软的MSChart,图既漂亮,且是原生的Dotnet代码,为什么还要使用老古董的ActiveX控件呢?原因是ActiveX控件有更好的交互性,另外ChartSpace控件可以使用PivotTable控件作为数据源,从而自动生成相应的图表,省了很多的代码。

本文记述了我在使用ChartSpace控件过程中的学习到的一些技术要点。

一. 和PivotTable控件关联

ChartSpace可以直接将PivotTable控件作为数据源,这样只要PivotTable控件的数据发生改变,图表也会发生相应的必变。代码如下:

 

chartSpace1.DataSource = pivotTable1;

 

在使用过程中,我发现了chartSpace的一个问题。如果PivotTable本身的数据源发生了改变,则ChartSpace的图形显示会不正常,它的坐标轴和图例是正确的,但是却没相应的图显示出来。解决的办法是先给ChartSpace控件的DataSource属性赋一个空值,然后再次将PivotTable控件赋值给DataSource属性。代码如下:

chart.DataSource = NothingOfVb();   // vbs function
chart.DataSource = pvt;  

上面代码中的函数NothingOfVb()是一个VBS函数,它返回一个值Nothing,代码如下:

< script type = " text/vbscript " language = " vbscript " >
       
'
        ' 返回vb中的nothing值
        '
        function NothingOfVb()
           
set NothingOfVb =   nothing
       
end function
       
</ script > 
之所以搞的这么复杂,是因为如果直接给ChartSpace.DataSource赋一个null,将会抛出异常“类型不匹配”。

二. 设置图表的类型

  ChartSpace控件提供了很多种图表类型,具体的可以参考它的API手册。常用的图表类型如下:

  1. this.chart.Charts.Item(0).Type = this.getChartType();

在使用过程中,有一个问题我至今没有解决。如果图表类型被设置饼图,那么每次只能显示第一个系列的数据,而实际会有多个系列的数据,我希望全部系列都显示出来(多个饼图的形式)或者通过代码指定要显示哪个系列的数据,可这两点我都没能做到。有知道怎么做的朋友麻烦告诉我一声。

三. 设置图表的外观

图表的外观基本上都是通过ChInterior对象来设置的。

下列属性返回 ChInterior 对象:
ChChart 对象的 Interior 属性
ChChartDraw 对象的 Interior 属性
ChartSpace 对象的 Interior 属性
ChDataLabel 对象的 Interior 属性
ChDataLabels 对象的 Interior 属性
ChDropZone 对象的 ButtonInterior 属性
ChDropZone 对象的 WatermarkInterior 属性
ChLegend 对象的 Interior 属性
ChPlotArea 对象的 Interior 属性
ChPoint 对象的 Interior 属性
ChSegmentBoundary 对象的 Interior 属性
ChSeries 对象的 Interior 属性
ChSurface 对象的 Interior 属性
ChTitle 对象的 Interior 属性

 

要设置拆线图的颜色,则需要设置ChSeries.Line.Color的值。要设置饼图的颜色,则要设置ChPoint.Interior返回的ChInterior对象的相关属性的值。以下是我工程中的部分代码:

 

设置图表外观
  1. // 柱状图
  2. if(chartType == chConstants.chChartTypeColumnClustered){
  3.     for(var i=0; i<this.chart.Charts(0).SeriesCollection.Count; i++){
  4.         var series = this.chart.Charts(0).SeriesCollection(i);
  5.         if(i < colors.length)
  6.             series.Interior.SetSolid(colors[i]);
  7.         else
  8.             series.Interior.SetSolid(randColor());
  9.                 
  10.     }    
  11. }       
  12. // 折线图
  13. else if(chartType == chConstants.chChartTypeLine){
  14.     for(var i=0; i<this.chart.Charts(0).SeriesCollection.Count; i++){
  15.         var series = this.chart.Charts(0).SeriesCollection(i);
  16.         if(i < colors.length)
  17.             series.Line.Color = colors[i];
  18.         else
  19.             series.Line.Color = randColor();
  20.     }    
  21. }        
  22. // 饼图
  23. else if(chartType == chConstants.chChartTypePie){            
  24.     for(var i=0; i<this.chart.Charts(0).SeriesCollection.Count; i++){
  25.         var points = this.chart.Charts(0).SeriesCollection(i).Points;
  26.         for(var j=0; j < points.Count; j++){
  27.             if(j<colors.length)
  28.                 points(j).Interior.SetSolid(colors[j]);
  29.             else
  30.                 points(j).Interior.SetSolid(randColor());
  31.         }
  32.     }
  33. }

 

上面的代码有点啰嗦,总的来说是给不同系列的图表设置颜色。

四. 导出图表

ChartSpace控件提供了一个名为ExportPicture(FileName, FilterName, Width, Height)的方法。从文档上看,应该可以用这个方法导出为图片,不过在实际用时却总是报异常。image

ChartSpace控件还有另一个方法GetPicture(FilterName, Width, Height)。这个方法可以获得导出图片的二进制数据。测试中,这个方法倒是没问题,顺利的获得了结果,是一个整数所数组。在Vs2008的监视窗口中也可以看到数组的内容。但神奇的是,我没有任何办法用Javascript或Vbscrip去访问数组的内容。经常一番Baidu,我找到了解决方案,使用MSXML2.DOMDocument。这是一个比较奇特折方法

 

  1. var data = this.chart.GetPicture('GIF',800,600);
  2.                 
  3.         var doc = new ActiveXObject('MSXML2.DOMDocument');
  4.         doc.loadXML("<xml xmlns:dt='urn:schemas-microsoft-com:datatypes'></xml>");        
  5.         var node = doc.createElement("file1");
  6.         node.dataType = "bin.base64";
  7.         node.nodeTypedValue = data;
  8.         doc.documentElement.appendChild(node);

 

基本断路是使用MSXML2.DOMDocument将二进制数组转换成base64编码的字符串,编码之后就可以通node.text属性获得结果。那么这个字符串如何保存为图片呢?我的解决方案是将它提交给服务器,然后解码回二进制再作为图片发送回客户端。显然,因为数据量的关系,提交时只能使用POST方式了。

 

  1. // 使用一个临时窗体将数据提交给服务器,并显示服务器返回的图片
  2.         var form = '<form action="PivotManager.aspx" name="form1" method="POST" style="visibility:hidden">' +
  3.                      '<input type="hidden" name="chart1" id="chart1" value="{0}" />' +
  4.                      '<input type="submit" value="exportChart" id="exportChart" name="exportChart"/>' +
  5.                      '</form>';
  6.         var script = '<script language="javascript">document.form1.exportChart.click();</script>';
  7.         
  8.         form = String.format(form,node.text);
  9.                 
  10.         var win = window.open("");
  11.         win.document.write(form);
  12.         win.document.write(script);

 

其中的String.format函数是Ext提供的,它的功能类似于C#中的Format函数。对应的服务器端代码如下:

 

  1. var buffer = Convert.FromBase64String(Request.Form["chart1"]);
  2.             Response.Clear();
  3.             Response.ContentType = "image/gif";
  4.             Response.AddHeader("Content-Disposition", "attachment;filename=chart.gif");
  5.             Response.OutputStream.Write(buffer, 0, buffer.Length);
  6.             Response.End();

 

整个过程是比较神奇的,先从ChartSpace中获取数据,编码后再提交给服务器,服务解码后再发送回客户端,真是无端的增加了服务器的负荷。

转载于:https://www.cnblogs.com/shangfc/archive/2010/12/13/1904109.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如何安装mschart#Region "定义变量" Const XOffset As Integer = 50, Yoffset As Integer = 20 Dim WithEvents PicCurve As PictureBox Dim xStep As Single = 5, yStep As Single Dim ValueArray As ArrayList Dim ThresHold() As Single 'HIHI、HI、LO、LOLO Dim Name As String = "参数名" Dim Unit As String = "单位" #End Region #Region "构造函数、析构函数" Public Sub New(ByVal mPictureBox As PictureBox, ByVal mThresHold() As Single, ByVal mName As String) ValueArray = New ArrayList PicCurve = mPictureBox ThresHold = mThresHold mPictureBox.BorderStyle = BorderStyle.None Name = mName End Sub Protected Overrides Sub Finalize() MyBase.Finalize() ValueArray.Clear() End Sub #End Region #Region "添加要绘制的点的信息" Public Sub AddValue(ByVal Value As Single) 'Value = ThresHold(0) * Rnd() + ThresHold(3) '测试代码 ValueArray.Add(Value) Call DrawCurve(GetGraphics(PicCurve)) End Sub Public Sub AddValues(ByVal Values() As Single, ByVal G As Graphics) For i As Integer = 0 To Values.Length - 1 ValueArray.Add(Values(i)) Next Call DrawCurve(G) End Sub #End Region #Region "绘制点之间的连线" Private Sub DrawCurve(ByVal G As Graphics, Optional ByVal mClear As Boolean = True) If ValueArray.Count > 0 Then If mClear Then G.Clear(Color.White) G.SmoothingMode = Drawing2D.SmoothingMode.HighQuality Dim mPoints(ValueArray.Count - 1) As Point, Position As Integer = XOffset For i As Integer = ValueArray.Count - 1 To 0 Step -1 Dim ThisValue As Single = CType(ValueArray(i), Single) 'If Position < PicCurve.Width Then Position += xStep Else Exit For Position += xStep mPoints(i) = New Point(Position, (ThresHold(0) - ThisValue) * yStep + Yoffset) Next G.DrawCurve(Pens.Blue, mPoints) mPoints = Nothing End If End Sub #End Region #Region "绘制坐标系统" Private Sub DrawReferenceFrame(ByVal G As Graphics) Dim mPoint1 As New Point, mPoint2 As New Point '定义绘图画笔 Dim MyPen As New Pen(Color.Black, 3) Dim MyStringFormat As New System.Drawing.StringFormat MyStringFormat.Alignment = StringAlignment.Center Dim mSize As New SizeF MyPen.SetLineCap(Drawing2D.LineCap.NoAnchor, Drawing2D.LineCap.ArrowAnchor, Drawing2D.DashCap.Flat) Dim mFont As Font = New Font(FontFamily.GenericSansSerif, 12.0F, FontStyle.Bold) '绘制Y轴 MyPen.Color = Color.Black mPoint1 = New Point(XOffset, PicCurve.Height) mPoint2 = New Point(XOffset, 0) G.DrawLine(MyPen, mPoint1, mPoint2) '绘制X轴 MyPen.Color = Color.LightGreen mPoint1 = New Point(XOffset, PicCurve.Height / 2) mPoint2 = New Point(PicCurve.Width, PicCurve.Height / 2) G.DrawLine(MyPen, mPoint1, mPoint2) '绘制参数名 MyStringFormat.FormatFlags = StringFormatFlags.DirectionVertical mSize = G.MeasureString(Name, mFont) mPoint1.Offset(-mSize.Height, 0) G.DrawString(Name, mFont, Brushes.Black, mPoint1, MyStringFormat) '绘制参数各门限 MyPen.DashStyle = Drawing2D.DashStyle.Dash : MyPen.Width = 2 MyPen.SetLineCap(Drawing2D.LineCap.NoAnchor, Drawing2D.LineCap.NoAnchor, Drawing2D.DashCap.Round) 'HI If ThresHold(1) <> ThresHold(0) Then MyPen.Color = Color.Yellow mPoint1 = New Point(XOffset, (ThresHold(0) - ThresHold(1)) * yStep + Yoffset) mPoint2 = New Point(PicCurve.Width, (ThresHold(0) - ThresHold(1)) * yStep + Yoffset) G.DrawLine(MyPen, mPoint1, mPoint2) mSize = G.MeasureString(ThresHold(1).ToString, mFont) mPoint1.Offset(-mSize.Width, -mSize.Height / 2) G.DrawString(ThresHold(1).ToString, mFont, Brushes.Yellow, mPoint1) End If 'LO If ThresHold(2) <> ThresHold(3) Then mPoint1 = New Point(XOffset, (ThresHold(0) - ThresHold(2)) * yStep + Yoffset) mPoint2 = New Point(PicCurve.Width, (ThresHold(0) - ThresHold(2)) * yStep + Yoffset) G.DrawLine(MyPen, mPoint1, mPoint2) mSize = G.MeasureString(ThresHold(2).ToString, mFont) mPoint1.Offset(-mSize.Width, -mSize.Height / 2) G.DrawString(ThresHold(2).ToString, mFont, Brushes.Yellow, mPoint1) End If 'HIHI MyPen.Color = Color.Red mPoint1 = New Point(XOffset, Yoffset) mPoint2 = New Point(PicCurve.Width, Yoffset) G.DrawLine(MyPen, mPoint1, mPoint2) mSize = G.MeasureString(ThresHold(0).ToString, mFont) mPoint1.Offset(-mSize.Width, -mSize.Height / 2) G.DrawString(ThresHold(0).ToString, mFont, Brushes.Red, mPoint1) 'LOLO mPoint1 = New Point(XOffset, PicCurve.Height - Yoffset) mPoint2 = New Point(PicCurve.Width, PicCurve.Height - Yoffset) G.DrawLine(MyPen, mPoint1, mPoint2) mSize = G.MeasureString(ThresHold(3).ToString, mFont) mPoint1.Offset(-mSize.Width, -mSize.Height / 2) G.DrawString(ThresHold(3).ToString, mFont, Brushes.Red, mPoint1) MyPen.Dispose() mFont.Dispose() End Sub #End Region #Region "要在其上绘制的控件事件" Private Sub PicCurve_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PicCurve.Paint Call DrawReferenceFrame(e.Graphics) End Sub Private Sub PicCurve_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles PicCurve.Resize On Error Resume Next xStep = 5 yStep = (PicCurve.Height - 2 * Yoffset) / (ThresHold(0) - ThresHold(3)) End Sub #End Region #Region "绘制永久图像" Function GetGraphics(ByRef pic As PictureBox) As Graphics Dim bmp As Bitmap = New Bitmap(pic.Width, pic.Height) pic.Image = bmp Dim g As System.Drawing.Graphics = Graphics.FromImage(bmp) Return g End Function #End Region #Region "保存图形" Public Sub SaveCurve(ByVal FileName As String) Dim bmp As New Bitmap(PicCurve.Width, PicCurve.Height) Dim g As Graphics = Graphics.FromImage(bmp) Call DrawReferenceFrame(g) Call DrawCurve(g, False) bmp.Save(FileName) End Sub #End Region End Class

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值