生活就好像一盒巧克力

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
Programming MS Office 2000 Web Components第三章第一节
第三章           图 表 组 件

 

至此我们已经熟悉了电子表格组件,现在让我们来研究图表组件的功能和编程模型。和前一章中一样,在介绍了一个特定功能后,我会讲述该功能的一些有趣用途。本书第二部分中,您会看到大部分功能在实际中的运用。

在本章中也会演示一些使用您自己的代码来为图表组件添加功能的巧妙方法。刚开始的时候您可能会觉得图表组件要比电子表格和透视组件复杂一些,但它具有一些可供您在解决方案中使用的强大功能。此外,它还提供了许多“配置选项”,您可以通过调节这些选项来根据您自己的爱好定制图表。

 

第一节           图 表 组 件 基 础

图表组件是一个COM控件,它就是由开发Microsoft Excel2000中的图表生成功能的小组开发的。它以位于界面的COM控件形式,以及位于内存中的GIF生成引擎形式来提供基本的商业图表生成功能。在现在这个第一个版本中,图表控件支持所有能在Excel中找到的二维图表类型(等高线图类型除外),另外还支持 极坐标图,堆积饼图,以及填充散布图表类型。当前这个版本不包括任何三维图表类型或效果。

本章中将会讨论的一个新特性是图表控件能够在一个组件的整个图表空间中显示多个图表。图表控件实际上是由一个包含一个或多个图表的完整图表空间组成的,这些图表都共享同一组相同的类别。(我会在本节后部详细解释术语“类别”)通常,在一个时刻,你只会在控件中包含一个图表;然而,在同一个图表空间中包含多个图表,使得可以很容易的快速比较相似信息。在本章结尾处我会详细讲述“图表空间”。

和电子表格组件一样,图表组件具有许多基本特性和一些独特的术语。在我们讨论更高级的主题之前,您应该熟悉这些特性和术语。

 

图表生成的术语

       在开发Excel2000图表生成功能的一个新特性时,OWC小组组织了大量的可用性测试,来检查是否我们的设计易于使用。如果您从来没有听说过这种测试,我可以解释一下,测试是这样的,我们从整个西雅图地区的公司和家庭中找来一些真正的顾客,向他们展示一个新特性的原型。我们要求这些人执行各种各样的任务,观察他们,以了解他们如何解决问题,以及是否我们的设计能够有效的帮助他们完成任务。我们常常发现现实情况与我们的期望相去甚远――这意味着必须回头重新设计这个特性。

       在一个测试中,我们向测试人员展示我们在Excel中创建的各种图表,并将图表中的某部分圈起来。我们要求他们告诉我们他们认为这些被圈起来的部分应该叫什么。从逻辑上说,您会期望我们找到一些共性,发现那个大多数人已经将它和某一特定元素关联起来的名称。然后我们就可以在我们的文档,编程模型,用户界面等地方使用这个名称。但是结果使我们十分沮丧,我们发现完全不能给这些图表元素提供一个标准名称。您可能认为人们应该知道哪个是x轴,哪个是y轴,但是许多人并不会记得多少数学课上学到的东西,而常常将它们搞混。

 

              注释

如果您正努力回忆哪个轴是X轴,哪个轴是Y轴,让我告诉您,X轴是水平方向的,Y轴是垂直方向的。当然,大多数图表都有被称为类别轴和数值轴的轴,而它们的方向是依赖于特定图表类型的。散布图和气泡图具有X和Y轴,因此这些图表上的各点之间要比较两个(或三个)值。在雷达图或极坐标图这样的图表类型中,轴实际上是从图表的中心延伸出去,因此X和Y轴就没有意义了。

       因为看来并不存在描述一个图表的元素的通用语言,所以讨论创建和操作图表就十分困难。为了获得任何对于图表组件的特性和编程模型的理解,我们都必须首先定义一系列用于组件的关键术语,并确定它们代表什么元素。许多术语在不同的图表类型中具有特殊的含义,因此,如果你在下面讨论中遇到一个您不熟悉的图表类型,可参考“支持的图表类型”一节,查看该图表类型相对应的屏幕截图和介绍。

 

系列

       系列是图表组件中最重要的结构之一。实际上,这个组件中的大部分内部结构都是围绕着系列的,图3-1中标记出了一个柱状图中的系列。请注意每个系列与图表的图例中的一项相对应。

       

 

图3-1。一个包含两个系列的柱形图。

 

       一个系列代表了希望以某种方式显示的多个数据点的一个序列。人们通常认为是图表具有一个独特的类型(例如线形图,条形图,或者饼图)。但是在图表控件中,具有独特类型的是系列――这意味着您可以通过设置一个系列为线形,而另一个系列为柱型来创建一个组合图表。一个系列中的所有数据点通常具有相同的颜色(但您可以改变这个颜色,我们后面会提到)。另外,例如趋势线和错误条这样的元素是和特定的系列相关的。

       缺省情况下,图例上的一项代表一个系列,但是如果需要,您可以隐藏图例中的某项。(后面将解释具体怎样做)

 

类别

       类别要比系列难解释一些。图3-2标记出了一个柱形图中包含的类别标签。

 

图3-2。柱形图中的类别。

 

       所有图表都有类别的概念,但并不是所有图表都有类别轴。在图3-2中,销售代表的名字是类别,每个系列包含各个类别上的一个单一数据点。大多数图表中,类别和系列的交叉点创建一个数据点。不过要注意的是,有些特别的系列和其它系列不同,它可能并不包含包含某个类别的数据点。例如,图表控件从所有系列中合并所有的类别,但在系列-类别的交集处不绘制数据点(???)。

       类别轴在三个重要的方面不同于数值轴。

u       各类别没有内在的顺序。

u       没有最小和最大的类别。

u       一个数据点仅分配给一个特定的类别。

 

       如果销售人员是您的类别轴,特定的销售数量就很自然与特定的销售人员相对应,在销售人员之间不存在数据点。而一个值轴有一个确定的最小值和最大值,在轴上的空间被平均分割为多个单元,当从最小值移向最大值时单元对应的值逐渐增加。因此不管位于轴的何处,每个数据点都能被标记。

       散布图和气泡图没有类别轴,因为它的数据点是由X坐标和Y坐标定义的,气泡图表的数据点还具有一个代表气泡尺寸的值。虽然这些图表类型没有类型轴,数据点仍然可以属于某个特定的类别,并且你也可以获得一个给定数据点的类别名。将额外的信息编码到散布图或气泡图中的数据点的机制是很有用的,它允许您在用户将鼠标停留在一个数据点上时显示这个信息。

              注释

显然,在真实的世界中,销售额可能常常属于多个销售代表。但大部分销售信息系统都将每个销售代表对销售的贡献分配合存储在一个数值中,这个数值会被标注在图表中。数据在类别中整齐分布的目的是使得可以使用连续的数值来比较离散的类别。例如,数值1.4567454可以在一个范围在0到2之间的数值轴中被标注,但是这个数值并不与类别在轴上的离散分布的容器相对应???

 

数值,数值,数值

       在大多数较简单的图表类型中,您只需要考虑一组数值。表3-3显示了以销售人员和年来标注的销售量。这个图表中每个数据点只包含一个数值――对于大部分简单图表类型来说都是这样的。

 

图3-3。柱形图中的数值。

 

       另一方面,散布图和气泡图表,则要求每个数据点必须包括两个或三个数值。在一个散布图表中,每个数据点有一个X值和Y值,这两个值的组合定义了一个二维空间,也就是笛卡儿空间中的点(X,Y)。气泡图表增加了第三个数值:一个决定了气泡以(X,Y)为中心的半径的气泡尺寸值。可以选择使用气泡的尺寸值代替半径来代表气泡的面积。

       当使用盘高-盘低-收盘图时,情况会更复杂一些,因为在这个图中又是三个值确定一个数据点,不过它们现在被称为盘高值,盘低值,和收盘值。一个开盘-盘高-盘低-收盘(OHLC)图表中每个数据点关联4个数值,当然,额外的那个数值被称为开盘值。(这些类型的图表常常被称为股票图表,因为它们通常主要是被用来显示股票数据。)

       当处理一个极坐标图时,您需要提供另一组数值:R值和Theta值。R值定义了数据点距图表中心的距离,Theta值代表了与通过原点的水平线之间的角度。

 



       您可能非常熟悉“轴”这个术语。在图表组件中,轴的含义和它在几何学上的含义基本上是相同的。不过,图表控件给轴添加了另一层含义,即将轴指定为类别轴或数值轴。在表3-4中,标明了类别轴和数值轴。

 

表3-4。      柱形图中的类别和数值轴。

 

       一个类别轴被分割成多个相等的段――每个代表一个单独的类别。而数据点被标注在每个类别的中间。对于类别轴来说,不存在最小值和最大值的概念。而另一方面,数值轴因为是一个连续的轴,所以它具有最小值和最大值。在数值轴上,数据点在最小值和最大值之间被标注在它们应该位于的地方。

       因为类别轴和数值轴的位置依赖于不同的图表类型,所以“类别”和“数值”只是逻辑的名称,而不能简单的直接映射为X轴和Y轴。例如,柱形图中的类别轴是沿底部(X)水平伸展的,而数值轴(Y)则是位于左方垂直上升的。但是在条形图中,位置正好相反,类别轴位于左边,而数值轴位于底部。可以参考“支持的图表类型”以了解各类型图表的更多信息。

 

缩放比例

       虽然您一定听说过术语“轴”,但您可能以前并没有听说过术语“缩放比例”。虽然您通常只在数值轴上使用缩放比例,但是其实每个轴都具有缩放比例,缩放比例定义了它对应的轴的度量刻度,决定了轴的最小和最大值。缩放比例也决定了轴上的间隔是线性的,还是对数的。线性尺度将轴分割成从最小值线性增加到最大值的平均的各段(例如,20,40,60,80,100)。对数尺度也将轴分割成平均的各段;但从一个段到下一个段是以对数,而不是线性来递增的(例如,1,10,100)。

       当本章后面部分讨论分割轴时,以及第6章中,我们会更加详细的讨论轴的缩放比例,在第6章中,我们还会看到如何通过“放大”来更加详细的显示您的数据中的一部分。

 

趋势线

       图表组件支持在您的图表中为每个系列创建一个趋势线。和在Excel中一样,一个趋势线常被用来显示各系列中数据的趋势。如果历史中的各值一直保持递增或递减,那么如果您需要预测将来会出现哪个值,就可以使用趋势线来进行趋势分析和预测。和在Excel中一样,图表控件提供几种不同的趋势计算方法,包括线性,对数,多项式,指数,以及权。然而,图表组件不提供Excel中的移动平均数趋势线类型。图3-5显示了一个趋势图的例子。

 

误差线

       图3-6显示了一个误差线,误差线是从数据点延伸出去的短线段,它指出了您的数据的某种不确定性,也就是误差值。每个数据点可以显示一个误差线,它表明数据点的真实值可能是误差范围中的任何一点。

       和趋势线一样,误差线是和系列相关的。系列中的每个数据点都会显示一个误差线,而这个系列的误差线的集合可以用来显示一个正的误差总量,一个负的误差总量,或者同时显示这两个。误差总量可以以百分比的形式(例如+10%, -10%, 或 +/-10%),相对值的形式(例如 +2, -2,或 +/-2),或者自定义误差的形式(例如, 对于数据点10来说,上届是12,下届是8)来表示。误差线也可以进行数据绑定,如果进行了数据绑定,则图表控件将各结果列中的值看作是每个数据点的自定义误差值。虽然Excel图表也为误差总量提供了标准误差和标准偏差选项,但图表控件本身并不支持这些功能。当然,您可以自己计算这些数值,并在图表中使用自定义的误差总量来显示它们。

 

              为什么要定义一个单独的缩放比例对象?

您可能疑惑于为什么缩放比例的概念不只是轴的一部分。毕竟,似乎是缩放比例决定了一个轴的最小和最大值。但是,缩放比例的最小和最大值决定了被称为绘图区的可视区域的尺寸。轴显示标记和标签,但是是缩放比例为绘图区的尺度确定了准确的点/值比例。通过将缩放比例从轴上分离出去,图表控件就能够支持没有可视轴的图表类型。

 

数据标签

       数据标签是位于数据点附近的一小段文字,您可以通过设置它来显示数据点的值、在系列中所占的百分比、类型名、系列名、或气泡的尺寸。(参见图3-7的例子)您可以在一个数据标签中显示这些信息片断的任意组合。此外,你还可以控制字体,颜色,边框格式等属性――甚至可以设置在每个信息片断之间使用哪种间隔字符。

 

图3-7。      柱形图中的数据标签。

       显然,当需要在您的数据点附近显示数字,尤其是需要比较那些可能值非常接近的数据点时,数据标签是十分有用的。在需要显示一个数据点在整个系列中所占的百分比时(例如在饼图中),使用数据标签显示百分比当然也是很有用的。在没有类别轴的图表(例如散布图和气泡图)中使用数据标签显示数据点的类别名也是一个很好的显示额外的类别信息的方法。

 

       和趋势线和误差线一样,数据标签是和系列相关联的。您不能对一个单独的数据点进行格式化,隐藏或显示的操作。所有针对数据标签的操作都会影响系列中的所有数据点。

       

 

支持的图表类型

       当我在介绍图表组件时,通常我从一个开发者的口中听到的第一个问题就是:“它支持那些图表类型?”图表类型是图表生成功能的基础,因此多多益善。在我的书架上有一本包含各种图表类型,图表元素和信息图形学技巧的参考书,它几乎有450页!(这本书是:《信息图形:全面图解指南[操作图形,1997]》,和其它任何Edward Tufte的书一样,对任何从事信息图形学的人来说,它都是一个极好的资源。)

       图形组件的第一个版本包括Excel2000中所有二维图表类型的集合(不包括等高线类型),另外,还包括极坐标图,堆积饼图,以及填充散布图类型。在这个版本的图表控件中不包含任何三维图表类型或效果,也不支持Excel提供的奇特的填充效果。

       让我们看一些图表组件支持的图表类型的例子,并讨论可以使用它们来显示哪种数据。

 

柱形图和条形图

       柱形图和条形图是在商业中最常用的图表类型,图表为每个数据点显示一个从数值轴上的零点延伸到数据点的被填充的条。

       大多数人并不在意柱形图和条形图之间的区别――毕竟,它们基本上是相同的,只是伸展的方法不同。图形组件使用术语“柱”来描述沿屏幕的上下方向扩展的垂直列,使用术语“条”来描述横跨屏幕延伸的水平条。表3-8显示了一个柱形图和一个条形图的例子。

 

 

图3-8。      柱形图(上面)和条形图。

 

       这些图表类型常用于显示那些包含不需要以某种特定次序显示的类别的数据。与线图不同,柱形图和条形图并不描述次序或级别的概念。

       和许多图表类型一样,柱形图和条形图有一些图表子类型。缺省的子类型,叫做簇状柱形图或簇状条形图,在每个类别中不同系列的标记条紧挨在一起。(图3-8显示了一个簇状柱形图和一个簇状条形图。)当不同的系列之间完全无关或它们不应在界面上被合并时,簇状子系统是最有用的子系统。例如,如果您在一个系列中标记预算值,而在另一个系列中标注实际值,那么您不会需要合并这两种数值。而是会需要将这两种柱形或条形并排放在一起,以便于比较。

       堆积柱形图和堆积条形图以一个堆叠一个的形式显示各系列。在这种图表中,柱或条的长度代表了类别对应的所有数据点的总和。表3-9显示了一个堆积柱形图的例子。

 

 

       图3-9。 一个堆积柱形图。

 

       在显示那些可以,并应该被合并起来,以便在视觉效果上描述每个类别总和的数据时,堆积柱形图和堆积条形图是很有用的。例如,如果您以国家和产品来标记销售量信息,您应该需要使用堆积柱形图来显示每个国家(类别)所有产品的总销售量,条仍然根据每个产品的销售量的准确值来进行分段――即高销售量的产品会拥有较长的段,而销售情况不好的产品会拥有较短的段。当不必考虑相对关系,而需要考虑每个类别的总和时堆积图表十分有用。

       最后,百分比堆积图表子类型有点象饼图:贯穿绘画区画一个条,或柱,然后将条,或柱根据每个系列的数据点所代表的百分比分割为多个段。这种子图表类型和堆积子图表类型的关键区别在于:各段的长度是数据点占类别中各数据点总和的百分比,而不是数据点的具体值。因为所有条的长度都相同(100%),因此这样的图表不能用来比较不同类别的总和。不过,这种类型的图表在查看饼图显示的相同类型的信息时很有用,但与饼图不同的是,它能同时查看来自多个类别和系列的信息。

       这里描述的大部分其它图表类型都具有同样的子类型集合――簇状,堆积,和百分比堆积。在后面的介绍中,我不再重复定义这三种子类型,不过需要的时候,我会作简单的说明。请回头参考本节,以了解这些子类型的介绍,以及哪种类型的数据适合于使用这些子类型显示。

 

饼图,堆积饼图,和圆环图

       饼图在商业图表中也很常见,它们只能显示最低密度的有用信息,并且也是最低效的,这几乎是一个极大的缺点。但是,它们的简洁也使它们非常易于理解,极具说服力。例如,当显示市场占有率的分类信息时,极大或极小的一块所带来的视觉效果确实是强有力的。图3-10显示了一个典型的饼图。

 

图3-10。一个饼图。

 

       饼图最重要的独特之处,是图例显示类别值,而不是系列值。大部分图表在图例中显示各系列,但因为饼图只显示一个系列,所以图例被用来显示对应各颜色饼“块”的类别的标记。

       显然饼图在显示百分比占有率或总量的细目分类信息时是很有用的。饼图之所以只显示一维数据的原因刚才我们已经提到了,那就是它只能显示一个系列的数据点。

 

       不过,堆积饼图和圆环图类型可以同时显示多个系列,这与百分比堆积柱形图可以同时显示多个系列和类别的数据很相似。堆积饼图和圆环图之间真正的唯一区别就是圆环图在中心有一个洞(如果您愿意,可以称为“圆环洞”)。图3-11描述了这样的信息,首先是一个堆积饼图,其后是一个圆环图。

 

       图3-11。一个堆积饼图和一个圆环图。

 

       我承认这两个图表类型有一些奇怪;实际上,我建议只有在没有其它图表类型能够满足需要的特殊环境中才使用它们(例如,在环绕爆炸地点的同心环中显示土壤中化学组成的百分比)。同心环可能会误导人们,因为它们的相对大小和顺序其实是抽象手锯,并不是基于某种数值的。

 

折线,平滑折线,以及面积图表

       折线图表和面积图表属于较为简单的图表类型,似乎它们应该常被使用,但遗憾的是,并不是这样的。图3-12显示了一个典型的折线图和面积图的样子。

       折线图和面积图在显示那些类别具有实际意义的次序的数据时十分有用,比如说一系列的日期或时间。例如,对于在一系列的日期上标记销售量或在一系列小时上标记股票价格的情况,使用折线图来显示比使用柱形图来显示更有效。这是因为在图表中的各数据点之间画上连线使得很容易说明哪儿有一个上升的趋势,哪儿有一个下降的趋势。

       折线图和面积图之间真正的唯一区别是,在面积图中,类别轴和折线之间的部分被系列的颜色所填充。对于一个系列的值比另一个系列的值大时发生的覆盖情况,面积图表处理起来比较困难――除非您使用的是我们前面提到的堆积子类型。因为系列是按照顺序依次绘制的,最后的系列会覆盖前面绘制的任何系列。因此只有在您确认一个系列的值一直都比后续的各系列的值高时,才应该使用不堆积的面积图。

 

图3-12。一个折线图和一个面积图。

 

       和柱形图、条形图一样,折线图和面积图也包括簇状、堆积和百分比堆积子类型。不过,术语“簇状”通常不用来描述缺省的子类型,这些缺省子类型只是简单的被称为折线图和面积图,而不加任何特别的限定。

       折线图具有一个柱形图和条形图没有的子类型。折线图中的折线可以画成“笔直的”或者“平滑的”。当然,使用平滑线来绘制的图表被称为平滑折线图。在这种图表类型中,图表控件使用有弧度的线条进行绘制,以消除参差不齐的峰谷。

       

散布图和气泡图

       有人认为,散布图能够成为比前面所介绍的较简单的图表类型更强有力的分析工具,但是不幸的是,它在商业图表中很少用到。虽然散布图具有系列和类别,但它也是通过两个值(而不是一个)来确定一个数据点的位置的。散布图中的每个数据点都具有一个X值和一个Y值,这两个值组合起来确定数据点在绘图区中的位置。

       散布图和气泡图的关键区别是气泡图中的数据点是具有动态大小的圆形。气泡图中的数据点包括名为气泡尺寸的第三个值,它决定了气泡的半径或面积。图3-13显示了典型的散布图和气泡图。

 

图3-13。一个散布图和一个气泡图。

 

       在比较两个不同的值以揭示相互关系或分配结构时散布图和气泡图十分有用。例如,使用散布图绘制一个部门的士气高低与部门收益之间的关系可以揭示一个明显的相关性:即高昂的士气通常会增加部门的收益。(至少,大部分雇员愿意相信它。)(??)

       散布图包含一些独特的子类型。缺省的子类型叫做标记散布图,它使用标记点(例如菱形或正方形这样的小几何形状)来代表数据点。不同的形状常用来代表不同的系列。您也可以选择使用平滑或者笔直的线段来连接每个系列中的标记点。还有,您还可以选择完全没有任何标记点的线段。图表组件包括一个Excel中完全没有包含的子类型。这个子类型允许您填充由数据点和连接线组成的多边形,这样就形成了“填充散布图”。

 

                     填充散布图的乐趣

您可以尝试一下随书光盘中一个相当有创造性的填充散布图的演示例子。打开文件夹Chap03夏的DrawWithChart.htm文件,点击图表界面,以创建一个填充多边形的各点。然后双击鼠标完成这个多边形。这个演示例子是由Jeff Couckuyt编写的,他是一位极为优秀的图表组件开发者,这个例子仅仅使用了图表控件和一个填充散布图表类型。

       

       记住气泡图表有和面积图表相同的覆盖的问题。一个大的气泡会隐藏任何它下方的数据点,因此只有在您确定覆盖的可能性很小的时候才使用气泡图表,否则,请考虑将气泡填充为透明的。

 

雷达图表

       雷达图似乎在美国并不怎么使用,但我知道在亚洲国家常用它来描绘例如食品中的营养成分这样的数据。图3-14显示了这个有趣和有用的图表类型的样子。

 

图3-14。一个雷达图。

 

       雷达图和其它简单图表类型一样,具有类别,系列和数值。但是,雷达图在一个环绕图表的圆环中绘制类别名称,并包括从图表的中心延伸导每个类别名称的轮辐。每个轮辐就是一个数值轴。每个类别的各数据点在相应轮辐上的相应点上,以相应的系列颜色进行绘制。

然后图表将各系列中的各数据点用线段连接起来,还可以选择将线段和原点之间的区域使用系列的颜色进行填充。填充雷达图表具有面积图和气泡图具有的相同的老问题,因此要小心使用填充子类型,除非您确定您的数据不会造成覆盖(或者您根本不关心这个问题)。

       雷达图也支持我们前面提到的平滑线子类型。另外,您还可以选择在平滑线和直线子类型上绘制数据点的标记。

 

盘高-盘低-收盘图和开盘-盘高-盘低-收盘图

       需要显示股票和金融证券信息的人会对这两种图表类型感兴趣。盘高-盘低-收盘图类型(HLC图表)为每个类别显示一个线段。每个线段从盘低值延伸到盘高值,并且专门通过一个小核对符号来指示收盘值。图3-15显示了一个HLC图表的例子。

 

图3-15。一个盘高-盘低-收盘图。

 

       在任何时候,如果您的数据中每个给定时段包含一列数据,并且在这列数据中有一个特别的数值需要被标记,那么您应该考虑使用这个图表类型。例如,您可以使用HLC图表来显示一段时间内的温度读数。

       开盘-盘高-盘低-收盘图(OHLC图)在HLC图的数据上添加了一段额外的信息:开盘值。该图表使用一个在开盘值和收盘值之间填充的矩形来显示开盘值,如图3-16所示。

       填充的矩形既可以是系列的颜色,也可以是黑色,这依赖与收盘值和开盘值之间的差值是正还是负。正的差值会显示正常的系列颜色,而负的差值会显示黑色。这就向观察者显示了某段时间内值发生了升高还是降低。这样他或她就能确定数值是变好还是变坏了,以及变好和变坏的程度任何。

 

图3-16。开盘-盘高-盘低-收盘图。

       HLC和OHLC图表类型依然保留了系列的概念。但是,在HLC图表类型中,图表组件在同一水平位置上放置不同的系列。换句话说,控件会在同一个地方重复的绘制各个系列。通常,这个图表类型在数据点只有一个系列时非常有用。另一方面,OHLC图表能够管理多个系列,并将多个系列的条紧挨着进行绘制。

 

极坐标图

       极坐标图形类型是Chart组件中出现的一个新图表类型,Excel图表功能中并不包含它。极坐标图,这个微软的Office用户一直以来都在要求的图表,在显示角度和距离之间的关系时十分有用。极坐标图表常用于音频领域和无线电领域中,例如,可以用来显示麦克风的拾音器的强度和方向。图3-17描述了一个典型的极坐标图表。

 

图3-17。极坐标图。

       极坐标图表包括平滑线子类型,并且您可以选择是否在线上显示数据点的标记。

 

组合图表

       在本章开始处我们提到过,图表生成最大的秘密之一就是一个图表实际上并不包括一个图表类型。而是每个单独的系列包含一个图表类型。如果一个图表中的所有系列碰巧包含的都是相同的类型,那么Chart对象的Type属性会返回这个类型。但是,您可以使用这个特性来创建更加复杂的组合图表,在其中,您可以将一些系列绘制成柱形或条形,而将另一些系列绘制成线性。

       不是所有的图表类型都能够被组合,在这个版本的Office中,图表组件只允许您对柱形,折线形,和面积图表类型进行组合。显示商业数据时最常用的组合图表是柱形图和折线图的组合。

 

装载数据

       您已经了解了各种图表元素的名称,以及图表控件能够显示那些图表类型,现在您需要学习如何将数据装载到图表中。和大多数Offic Web组件一样,图表控件可以从多种数据源中装载数据,并且装载的过程可以在设计环境中使用图表向导来完成,或通过编写代码来完成。图表组件可以绑定到所有其它的Office Web组件上――电子表格组件,透视表组件,以及数据源组件――还有所有实现了IDataSource接口(这个一个微软IE和VB中的数据源控件所具有的标准接口,在微软开发者网络图书馆和OLE DB SDK中有关于它的文档)的其它控件,ADO的Recordset对象,甚至是文本数据的数组或使用分隔符分隔的一系列数据组成的字符串。

       将数据装载到图表控件中的常用方法是:告诉图表应该从哪里获得数据,以及数据源的哪部分应该用于当前图表类型所需要的系列,类别和值。在编程模型中,图表控件将这些可以绑定到数据源的某部分的图表元素称为dimensions。当绑定到一个电子表格时,您指定的数据源的“部分”就是一个range的引用,例如A1:C1。如果绑定到一个OLE DB数据源时,您就应指定使用结果集中的哪一个列名或者列的下标。而对于透视控件,您应指定使用哪一个透视轴。(我们将在第4章中进一步讨论这个问题),而对于文本数据来说,只有一种“部分”存在:数组或具有分隔符的字符串本身。

       图表向导通过为您提供一个简单的指定这种绑定信息的用户界面,帮您完成了大部分的绑定工作。但实际上图表向导只是调用了图表控件的公共编程模型,因此如果通过编写代码,您能够完成任何图表向导的功能,并能完成图表向导所不具备的功能。图表向导的使用是相当明白的,它的在线帮助也包含了大部分的使用方法。因为本书主要着眼于使用Office Web组件开发定制的解决方案,所以我不会在这里详细介绍如何使用图表向导。而会深入到那些当通过编程将数据装载到图表中时您必须编写的代码中去。

 

使用文本数据装载图表

       下面的子过程,取自随书光盘中Chap03文件夹下的LoadFromLiteral.htm文件,它显示了如何将文本数据装载到图表控件中:

'------------------------------------------------------------------------

' LoadChartWithLiteral()

' 目的: 将文本数据装载到图表中

' In:      cspace        ChartSpace对象的引用

'          vSeries       变量数组或以tab分割的字符串,代表各系列名。

'          vCategories   变量数组或以tab分割的字符串,代表各类别名。

'          avValues      变量二维数组或以tab分割的字符串,代表各数值;

'                        外围数组中的一项代表一个系列。

'

Sub LoadChartWithLiteral(cspace, vSeries, vCategories, avValues)

    ' 局部变量

    Dim cht    ' 我们将在图表空间中创建的Chart对象。

    Dim ser    ' 临时系列

    

' 获得常量对象以便我们可以在脚本中使用常量名称。注意:只是在VBScript中需要这样做,

' 而在VBA中并不需要。

    Set c = cspace.Constants

    

' 清除图表空间中。

cspace.Clear

 

    ' 在图表空间中创建一个图表。

    Set cht = cspace.Charts.Add()

    cht.HasLegend = True

    

    ' 现在调用SetData函数来绑定各个dimensions

' 第二个参数是c.chDataLiteral, 说明最后一个参数是一个变量数组或是一个

    ' 以tab分隔的字符串。

    cht.SetData c.chDimSeriesNames, c.chDataLiteral, vSeries

    cht.SetData c.chDimCategories, c.chDataLiteral, vCategories

    

    ' 当使用文本数据装载图表时,您必须使用数值分别装载每个系列。

    For each ser In cht.SeriesCollection

        ser.SetData c.chDimValues, c.chDataLiteral, avValues(ser.Index)

    Next 'ser

    

End Sub 'LoadChartWithLiteral()

 

       当使用文本数据装载图表时,数据既可以包含在变量数组中,也可以包含在以tab分隔的字符串中,每一个元素或标记都代表了一个不同的数值。在随书光盘的文件中,我使用了Array函数将文本数据以数组的形式进行传递。在微软的VBScript和VBA中都支持这个函数。

       SetData方法被用来传递文本数据,但是请注意第二个参数(通常是数据源的下标)是常量chDataLiteral。这个等于-1的常量,告诉图表下一个参数是文本数据,而不是一个数据源的一部分。

       还要注意的是,在将文本数据传递给图表时您必须使用Wcseries对象(代表一个系列的对象)的SetData方法。因为一个图表控件自身只能接受一维数组的值,如果允许您将文本数据传递给WCChart对象(代表一个图表的对象)的SetData方法,它将无法判断一个值应该属于哪一个系列。前面的过程通过简单的遍历系列集合,并将相应的数组的值传递给当前系列的SetData方法来解决了这个问题。

 

绑定到电子表格组件

       下面的子过程,来自随书光盘中Chap03子目录下的LoafFromSpreadsheet.htm文件,它演示了如何将图表组件绑定到电子表格组件的区域上。

'-------------------------------------------------------------------------

' BindChartToSpreadsheet()

'

' 目的: 将一个图表绑定到源电子表格中的指定区域上。

' 传入参数:cspace           ChartSpace对象的引用

'          sheet            Spreadsheet对象的引用

'          srngSeries       字符串区域的引用,其中定义了系列的名称

'          srngCategories   字符串区域的引用,其中定义了类别的名称

'          srngValues       字符串区域的引用,其中包括了各个数值

'

Sub BindChartToSpreadsheet(cspace, sheet, srngSeries, srngCategories, _

                           srngValues, fSeriesInCols)

    ' 局部变量

    Dim cht          ' 将在图表空间中创建的Chart对象

    Dim ser          ' 临时系列

    Dim rngValues    ' 存储各数值的Range对象

    

    Set c = cspace.Constants

    

    cspace.Clear

 

    ' 首先告诉图表它的数据来自于电子表格

    Set cspace.DataSource = sheet

    

    ' 在图表空间中创建一个图表。

    Set cht = cspace.Charts.Add()

    cht.HasLegend = True

    

    ' 现在调用SetData方法来绑定各个dimensions

    ' 第二个参数是0,说明如果有多个数据源,应该使用第一个数据源。

    cht.SetData c.chDimSeriesNames, 0, srngSeries

    cht.SetData c.chDimCategories, 0, srngCategories

    

    ' 电子表格子只能绑定到一维区域上,

    ' 因此遍历系列集合,并单独为每个系列设置数值。

    Set rngValues = sheet.Range(srngValues)

    

    For Each ser In cht.SeriesCollection

        If fSeriesInCols Then

            ser.SetData c.chDimValues, 0, _

                rngValues.Columns(ser.Index + 1).Address

        Else

            ser.SetData c.chDimValues, 0, _

                rngValues.Rows(ser.Index + 1).Address

        End If

    Next 'ser

    

End Sub 'BindChartToSpreadsheet()

 

       现在说明这个例子的一些相关信息。首先,为了将图表和电子表格空间绑定起来,我将图表控件的DataSource属性设置为电子表格控件的实例。在接收到指向电子表格控件实例的指针后,图表控件就可以向电子表格控件请求某个区域中的单元格的数值。

       第二,使用SetData方法首先绑定系列名称维,然后是类别维。您必须使用这个顺序来绑定图表的各维:先是系列名称,然后是类别名称,最后是数值。在一些少见的例子中,您只有一个系列的信息,你可以跳过设置系列名称维,而只绑定类别和数值。这样做会使控件使用缺省的名称“Series”来为您创建一个系列,您可以通过设置WCSeries对象的Name或Caption属性来改变这个名称。

       我要谈到的最后一点是,当绑定到电子表格组件上时,Chart组件需要接收到每个系列的准确的区域引用。遗憾的是,您不能将一个二维区域的数值传递给图表,并让它自动判断各数值属于那一个系列和类别。您必须将一个一维区域的引用传递给每个WCSeries对象的SetData方法的最后一个参数。前面的例子使用一种常用的方式来完成这个任务:使用电子表格组件的Range对象来获得在二维区域中每列或每行的一个区域引用。并依次将它传递给各系列的SetData方法。标志fSeriesInCols说明一个指定系列的各数值是在电子表格中按列排列还是按行排列。如果标志为真,将使用列的集合;如果为假,将使用行的集合。

       还需要说明的是,例子中在系列的下标值上加上1。这是因为为了保持与Excel编程模型的兼容性,列和行集合的下标是以1为基础的。而图表组件的系列的下标是以0为基础的。将系列的下标加1,从而获得相对应的区域中列或行的下标。

 

绑定到数据源组件

       下面的方法,来自随书光盘中Chap03子目录下的LoadFromDSC.htm文件,它演示了如何将图表组件绑定到从数据源组件(DSC)返回的一个记录集上。(我们将在第5章中详细的讨论DSC。)

'------------------------------------------------------------------------

' BindChartToDSC()

'

' 目的: 将图表绑定到数据源组件的一个记录集上。(这个例子创建一个饼图。)

' 输入参数:cspace        ChartSpace对象的引用

'          dsc           数据源控件的引用

'          sRSName       绑定到的数据源控件中记录集的名字 

'          sCategories   包含类别的结果列的名称

'          sValues       包含数值的结果列的名称

'

Sub BindChartToDSC(cspace, dsc, sRSName, sCategories, sValues)

    ' 局部变量

    Dim cht    ' 将在图标空间中创建的Chart对象

    Dim ser    ' 临时系列

        

    Set c = cspace.Constants

        

    cspace.Clear

 

    ' 首先告诉图表它的数据来自数据源控件。

    Set cspace.DataSource = dsc

        

    ' 接着告诉它数据源控件中它将会被绑定到的记录集

    cspace.DataMember = sRSName

        

    ' 在图表空间中创建一个饼图。

    Set cht = cspace.Charts.Add()

    cht.HasLegend = True

    cht.Type = c.chChartTypePie

        

    ' 现在调用SetData函数绑定各维,第二个参数为0,说明如果有多个数据源,应该使用第一个

 

    ' 在这个饼图的例子中,我们将手工添加一个系列,并使用这个系列的SetData方法 

    Set ser = cht.SeriesCollection.Add()

    ser.SetData c.chDimCategories, 0, sCategories

    ser.SetData c.chDimValues, 0, sValues

        

    ' 最后,为这个例子添加一些数据标签,因为它是一个饼图。

    Set dls = ser.DataLabelsCollection.Add()

    dls.HasPercentage = True

    dls.HasValue = False

 

End Sub 'BindChartToDSC()

 

       DSC既可以从图标组件和透视组件中提取数据,也可以为二者提供数据。它也实现了Visual Basic和IE的数据源控件所实现的相同的数据源COM接口(IDataSource),因此,这段代码可以被这些环境中的任何其它有效的数据源控件所使用。

       ChartSpace对象的DataSource和DataMember属性是这个例子的基础。因为他们是由Visual Basic和IE所建立起的数据绑定标准的一部分,所以你常会在这些环境中的其它数据绑定控件中看到它们。DataSource属性被设置为只想提供数据的控件(在这个例子中是DSC),而DataMember属性被设置为命名所需要的特定数据集的字符串。因为一个DSC可以同时暴露多个数据集,所以DataMember属性被用来告诉图表控件应该请求那个数据集。如果您不设置DataMember属性。图标控件会请求缺省的数据集,具体哪个是缺省数据集,是由DSC决定的。

       本例中使用SetData方法的方式与在BindChartToSpreadsheet方法中使用SetData方法的方式极为相似,除了函数调用中的“数据部分”(SetData函数的最后一个参数)现在变成了DSC返回的记录集中一个列的列名。数据部分还可以是列的列下标(0,1,2,等等)。图表控件将把数据部分的值传给给ADO的Fields集合对象的Item方法,因此任何这个Item方法认为有效的参数都可以在SetData方法的最后一个参数中被使用。一般来说,如果您认为列名不会在将来改变,但列的顺序会在将来改变,那么您应该使用列名,而如果您认为将来列名会改变,而列的顺序不会变化,那么应该使用列的下标。

       前面提到过,饼图的一个有趣的特性是图例中的项是类别,而不是系列。因此,当绑定一个饼图时,您应该将您希望显示在图例中的列绑定到类别维上,而不是绑定到系列维上。这也适用于堆积饼图和圆环图。

       本例中最后一段代码创建了一些数据标签(我们刚刚讨论过)来显示每个数据点在总体中所占的百分比。图表控件可以为每个数据点显示许多数值,缺省是显示实际的数字数值。因为我只希望显示每一片所占地百分比,所以我将HasPercentage属性设为True,而将HasValue属性设为False。

       虽然这个特定的例子创建的是一个饼图,但是您可以在绑定到DSC上时使用任何支持的图表类型。我选择在这个例子中创建饼图只是为了说明在使用饼图时是如何实现绑定的。

 

绑定到数据集

       下面的函数,来自随书光盘中Chap03子目录下的LoadFromRecordset.htm文件,它演示了如何将一个图表控件绑定到一个ADO记录集对象上:

'------------------------------------------------------------------------

' BindChartToRecordset()

'

' 目的: 将一个图表绑定到一个记录集上(本例中创建的是一个散布图。)

' 传入参数:cspace        ChartSpace对象的引用

'          rst           要绑定到的Recordset对象的引用

'          sfldSeries    系列的字段名

'          sfldXValues   包含X数值的字段名

'          sfldYValues   包含Y数值的字段名

'

Sub BindChartToRecordset(cspace, rst, sfldSeries, sfldXValues, _

    sfldYValues)

    ' Local variables

    Dim cht    ' Chart object that we'll create in the chart space

    Dim ser    ' Temporary series pointer

    Dim ax     ' Temporary axis pointer

        

    ' Grab the Constants object so that we can use constant names in

    ' the script. Note: This is needed only in VBScript -- do not include

    ' this in VBA code.

    Set c = cspace.Constants

        

    ' Clear out anything that is in the chart space

    cspace.Clear

 

    ' First tell the chart that its data is coming from the Recordset

    Set cspace.DataSource = rst

        

    ' Create a Scatter chart in the chart space

    Set cht = cspace.Charts.Add()

    cht.HasLegend = True

    cht.Type = c.chChartTypeScatterMarkers

        

    ' Now call SetData to bind the various dimensions

    ' Second parameter is zero, meaning the first data source should be

    ' used if there are multiple data sources 

 

    ' In this example of a Scatter chart, we will bind

    ' two value dimensions: X and Y

    cht.SetData c.chDimSeriesNames, 0, sfldSeries

    cht.SetData c.chDimXValues, 0, sfldXValues

    cht.SetData c.chDimYValues, 0, sfldYValues

        

    ' Finally, let's add some axis labels using

    ' the column names as the axis captions

    Set ax = cht.Axes(c.chAxisPositionBottom)

    ax.HasTitle = True

    ax.Title.Caption = sfldXValues

    ax.Title.Font.Name = "Tahoma"

    ax.Title.Font.Size = 8

    ax.Title.Font.Bold = True

    ax.NumberFormat = "#,##0"

            

    Set ax = cht.Axes(c.chAxisPositionLeft)

    ax.HasTitle = True

    ax.Title.Caption = sfldYValues

    ax.Title.Font.Name = "Tahoma"

    ax.Title.Font.Size = 8

    ax.Title.Font.Bold = True

    ax.NumberFormat = "$#,##0"

        

    ' Let's also set the marker size a bit smaller than normal

    For Each ser In cht.SeriesCollection

        ser.Marker.Size = 5

    Next 'ser

 

End Sub 'BindChartToRecordset()

 

       毫无疑问,您会立刻注意到这个例子除了使用的是散布图之外,它和前面包括DSC的例子很相似,这是因为在Visual Basic和IE中ADO的记录集对象本身就是一个有效的数据源。它也实现了与DSC相同的数据源接口。这使得可以采用和使用DSC时设置图表控件的DataSource属性一样的方式将控件的DataSource属性指向记录集对象。但是,记录集对象被定义为只能暴露一个数据集,因此在绑定到记录集上时不需要设置DataMember属性。

       因为在本例中使用的图表类型是散布图,所以代码设置了两个数值维:X值和Y值。在前面“支持的图表类型”一节中讲到过,散布图对每个数据点使用两个数值,因此我们需要将X数值维绑定到记录集中的一列上,而将Y数值维绑定到另一列上。(您可以将它们都绑定到同一列上,但是这样会产生一个高度相关的散布图!)

                     良好架构造成的一次意外

当我将本章交给图表组件开发者们浏览时,一位开发者提出,实际上组件并不“支持”从记录集中加载,而且OWC小组也没有正式测试过这个功能。但我们在内部编写的几乎所有演示和实际的页面都使用了这个方法,因此,实际上这个功能是相当稳定的。

将记录集装载到图表组件中能够正常工作的原因是良好架构造成的一次意外。当Visual Basic和IE开发小组选择了标准的数据源接口(IDataSource)时,ADO小组认为让Recordset对象实现这个接口是很有意义的,因为这样它就能从GetDataMember方法中方便的返回底层的IRowset接口。因为图表控件在从DSC中装载数据时使用IDataSource接口,所以Recordset对象正好能够很好的工作。对于图表控件来说,记录集对象和其它数据源控件是完全一样。

       当绑定到记录集对象时,您必须确定记录集正在使用微软Windows游标引擎(WCE)或者能够被浏览和游历。WCE是一个ADO组件,它能够在任何OLE DB 记录集上提供了浏览、排序、过滤和其它功能,而不必考虑记录集的来源或原始功能。为了使用这个引擎,需将您的ADO连接或记录集的CursorLocation属性设置为adUseClient,如果您所使用的环境不能识别这个常量,可以使用它的值――3来代替。为了保证图表控件能够在记录集中进行游历,您可以使用adOpenStatic游标类型,它的值也是3。在记录集的Open方法的CursorType参数中,或Recordset对象的CursotType属性中使用adOpenStatic或者3(第4章中会详细讨论WCE)。

       请浏览随书光盘中LoadFromRecordset.htm文件里的完整源码清单来查看设置这个必须设置的记录集属性的例子。当浏览这个文件时,注意例子使用列名作为轴的标题。散布图具有两个数值轴(X轴和Y轴),因此您应该为这些轴设置标题来解释您在这些轴上显示的是什么数值。使用记录集中的列名来标注这些轴是一个简便的方法;当然,如果记录集中的列名难以理解,您可以使用您自己的标题来进行设置。

 

绑定到透视组件

       图表组件最后一个可能的数据来源是透视组件。(在下一章中将详细的讨论这个组件。)和您所猜想的一样,这个组件也实现了与VB和IE中所有有效的数据源所暴露的数据源接口相同的接口,因此下面这个从随书光盘的Chap03文件夹下的LoadFromPivot.htm文件中取出的例子,和我们前面所讨论的DSC的例子很相似,但是也有一些重要的不同:

'------------------------------------------------------------------------

' BindChartToPivot()

'

' Purpose: Binds a chart to a PivotTable component

' In:      cspace          reference to the ChartSpace object

'          ptable          reference to the PivotTable object

'          fSeriesInCols   Boolean flag indicating whether the series

'                          of the chart should come from the column

'                          axis or the row axis of the PivotTable control

'

Sub BindChartToPivot(cspace, ptable, fSeriesInCols)

    ' Local variables

    Dim cht    ' Chart object that we'll create in the chart space

    Dim ax     ' Temporary axis reference

    Dim fnt    ' Temporary font reference

    

    ' Grab the Constants object so that we can use constant names in

    ' the script. Note: This is needed only in VBScript -- do not include

    ' this in VBA code.

    Set c = cspace.Constants

        

    ' Clear out anything that is in the chart space

    cspace.Clear

 

    ' First tell the chart that its data is coming from the

    ' PivotTable component

    Set cspace.DataSource = ptable

        

    ' Create a chart in the chart space

    Set cht = cspace.Charts.Add()

    cht.HasLegend = True

    cht.Type = c.chChartTypeBarClustered

        

    ' Now call SetData to bind the various dimensions

    ' Second parameter is zero, meaning the first data source should be

    ' used if there are multiple data sources

    If fSeriesInCols Then

        cht.SetData c.chDimSeriesNames, 0, c.chPivotColumns

        cht.SetData c.chDimCategories, 0, c.chPivotRows

    Else

        cht.SetData c.chDimSeriesNames, 0, c.chPivotRows

        cht.SetData c.chDimCategories, 0, c.chPivotColumns

    End If 'fSeriesInCols

    

    ' Set the values dimension. The value

    ' you pass for the data reference (the last parameter)

    ' is the index of the total you want to use.

    ' Since there is only one total in this example,

    ' we pass zero, indicating the first one.

    cht.SetData c.chDimValues, 0, 0

        

    ' Finally, let's add an axis title to the value

    ' axis, using the label on the pivot total

    ' as the caption, and set the number format

    Set ax = cht.Axes(c.chAxisPositionBottom)

    ax.HasTitle = True

    ax.Title.Caption = ptable.ActiveView.DataAxis.Totals(0).Caption

    Set fnt = ax.Title.Font

    fnt.Name = "Tahoma"

    fnt.Size = 8

    fnt.Bold = True

    

    ax.NumberFormat = ptable.ActiveView.DataAxis.Totals(0).NumberFormat

    

End Sub 'BindChartToPivot()

 

       和前面的记录集合DSC例子一样,为了将图表控件绑定到透视控件,首先您将图表控件的DataSource属性设者为指向透视表控件的一个实例。和记录集的例子一样,透视表控件只暴露一个数据集,因此您不必改变DataMember属性的缺省设置。

       本例和DSC的例子的关键区别是用于SetData方法最后一个参数的特定常量。您应该记得,这个最后参数定义了您需要将哪部分的数据绑定到指定的图表维。在透视表控件中,有效的逻辑部分是行和列的透视轴,以及试图中的所有总和。在透视表控件中,行轴指显示在表左下方的所有标签,而列轴指显示在横穿表顶部的所有标签(下一章将更多的讲述这些轴)。图表控件都必须知道的所有信息就是:您需要将哪个轴绑定到系列名称维上,哪个轴绑定到类别维上。

       本例中绑定图表控件的各个值维的方式有一些不同。因为一个透视表报表能够同时显示许多总和值,所以图表控件必须知道您需要将哪个总和用于指定的值维。这是通过将一个总和的下标传递给SetData方法的最后一个参数来指明的。在BindChartToPivot例子中,我们使用了簇形柱形图,因此每个数据点只有一个数值。我们告诉图表控件使用下标0处的总和(即第一个,因为是从0开始的)作为数据点的数值。注意这是在透视表控件的当前视图中有效总和中的下标――而不是数据源中所有可能的总和。

       但透视表控件确实实现了一个数据源控件所需要的标准COM接口,它只是不知道如何返回ADO记录集和OLE DB行集合。图表控件中包含了专门的代码,以实现读取透视表控件中显示的交叉数据,并恰当地忽略了子总计和外部总计,如果使用这些总计,将会扭曲图表的刻度,并不是所有的数据绑定控件都能将透视表控件用作它们的数据源。

 

图表和轴的标题

       图表因为以易于理解,可视的方式显示大量的信息,而成为一种高效的机制。但是,绘制在图表中的数据几乎不能自我描述;因此您经常需要为您的图表和在图表中显示的轴添加一个描述性的标题。

                     为多值的图表使用多个总和

       散布图、气泡图、极坐标图,和OHLC图表类型都有一个相同的地方:它们需要使用多于一个的数值来确定图表中的一个数据点。散布图需要X值和Y值,气泡图也需要这两个值,还有一个气泡尺寸值,极坐标图需要Theta和R值,而OHLC图,就像它的名称所表明的一样,需要4个数值。因为透视表报表一次可以显示多个总和,所以常常希望将这些总和映射为不同的图表数值,以便形成一个单个数据点。

       您可以通过在SetData方法最后一个参数中指定透视表视图中总和的下标来完成这个任务。例如,为了将第一个总和绑定到散布图的X上,而将第二个总和绑定到Y上,您应该书写这样的代码:

cht.SetData c.chDimXValues, 0, 0    ' First total

cht.SetData c.chDimYValues, 0, 1    ' Second total

       有时您需要在一个数据点只使用一个数值的图表类型中使用这些多个总和,例如堆积柱形图。在这种情况下,您可能希望将总和的标题显示为一个嵌套类别或一个嵌套系列的标签。您可以使用一个特殊的常量来完成这个任务:

cht.SetData c.chDimCategories, 0, c.chPivotRowAggregates

       这个设置将使用显示在行轴上的任何总和标题作为分级的类别轴的嵌套类别名称。为了得到您需要的结果,您还应该将PivotView对象的TotalsOrientation属性设置为plTotalOrientationRow常量,以便总和的标题显示在每一行上。

       可能您需要将多个总和在图表中显示为不同的系列。为了完成这个任务,将PivotTable报表上的列轴保持为空,添加上您需要显示为不同的系列的总和,然后书写下面的代码:

cht.SetData c.chDimSeriesNames, 0, c.chPivotColAggregates

       这段代码将在图表中为PivotTable报表中的每个总和创建一个系列。请参考随书光盘中Chap03文件夹下的PivotTotalsAsSeries.htm例子文件,并查看它的具体做法。

 

       如果您将多个图表添加到图表控件中(在“图表空间中的多个图表”一节中会详细介绍),您可以为每个图表设置它们自己的标题。实际上,您可以为图表控件自身设置一个全局的标题,他会显示在所有单独的图表的上方。可以使用所有的基础字体属性(字体名称,大小,是否黑体,是否斜体,是否具有下划线,颜色)来格式化图表标题。您也可以设置它们的背景色,或者让它们保持透明。对于轴标题也是一样的。

       缺省情况下,新创建的图表不会具有图表标题和轴标题。您可以在设计阶段使用属性工具箱来添加图表标题和轴标题,也可以使用代码在运行阶段设置。下面这段来自随书光盘Chap03文件夹下的AddTitles.htm文件的方法,演示了如何添加一个图表标题:

'------------------------------------------------------------------------

' SetChartTitle()

'

' Purpose: Sets the chart's title

' In:      cht      reference to a chart

'          sTitle   new title caption

'

Sub SetChartTitle(cht, sTitle)

    Dim fnt    ' Temporary font reference

    

    ' If the title is nonblank

    If Len(sTitle) > 0 Then

        ' Add a title if necessary

        cht.HasTitle = True

        

        ' Set the caption and its font formatting

        cht.Title.Caption = sTitle

        Set fnt = cht.Title.Font

        fnt.Name = "Tahoma"

        fnt.Size = 10

        fnt.Bold = True

    Else

        ' Title is blank. Remove it.

        cht.HasTitle = False    

    End if

End Sub 'SetChartTitle()

 

       您可以使用与添加图表标题相同的方法添加轴标题,除了一个区别:方法的第一个参数接受一个Axis对象的引用,而不是一个图表对象的引用。

       还要注意您既可以将标题的字体或者背景的Color属性设置为一个RGB颜色值,也可以将它设置为一个IE的颜色名称――例如,“FireBrick”或者“PapayaWhip”。这也适用于图表控件中任何使用颜色的地方,例如图表的背景色,绘图区的颜色,系列的颜色,等等。

 

轴标签

       缺省情况下,图表控件会在您所有轴上设置标签,以便显示数据点位于刻度上的何处(值轴),或数据点属于那个类别(类别轴)。您可能需要在运行阶段使用代码,或在设计阶段使用属性工具箱调整这些标签的一些外观。

       对于值轴来说,标签显示了轴上全部值刻度的数字点。这些数字最初都没有被格式化,除非数据源是一个单元格包含了明确的数字格式化信息的电子表格。为了改变缺省的数字格式,可以将轴的NumberFormat属性设置为一个新的数字格式名称或者格式字符串。您可以使用的格式名称的列表位于电子表格控件的帮助文件(通过点击电子表格上的帮助按钮可以打开这个文件)中的“电子表格中的数字格式化”主题下。您也可以象在Excel中一样创建一个自定义的格式字符串,在自定义数字格式中可以使用的符号可以在Excel2000的帮助文件中找到,相关的概要主题标题是“创建一个自定义的数字格式。”

       对于值轴和类别轴,您都可以选择丢弃一些标签――例如,每五个标签中只显示第五个。这对于那些包含太多标签的轴来说很有用,可以使轴上的标签不至于重叠,还有对于那些可以从保留的标签中推导出那些被丢弃的标签的图表来说,这也很有用,例如,一系列的日期。 类别轴缺省是不取消标签的。但是假设您在类别轴上包含一大组的时间。您可以通过设置相应WCAxis对象的TickLabelSpacing属性来选择取消一部分标签,即可以采用在设计阶段选择标签并使用属性工具箱的方式来完成,也可以通过运行阶段的代码来完成。这个属性的设置决定了在显示的标签之间要跳过多少标签。注意这个属性只影响标签,这意味着轴仍然会在标签应该显示的地方显示标记符号。不过,您也可以通过将TickMarkSpacing属性调整为TickLabelSpacing属性相同的值来减少一些标记符号。

 

图例

       缺省情况下,新创建的图表不包含图例。如果您计划显示多个系列的数据点,您可能需要为您的图表添加一个图例,以说明哪种颜色对应哪个系列。既可以在设计阶段通过选择图表,并使用属性工具框来添加图例,也可以在运行阶段通过代码将WCChart对象的HasLegend属性设置为True来添加图例。

       最初,图例缺省为每个系列包含一项,但是您可以改变它。为了隐藏一个图例的项,使用WCLegend对象的LegendEntries集合来获得您需要隐藏的图例项,然后将获得的对象的Visible属性设为False。在设计阶段,您可以简单的选择图例项,并通过按Delete键来删除它。

       如果您在图表控件中包含了多个图表,您可以为每个单独的图表创建一个图例,或者您也可以为整个控件创建一个图例。例如,如果您在显示多个饼图,可能为所有的饼图只显示一个图例更有意义,因为颜色/类别的映射对每个图表都是一样的。如果一组系列在各图表之间的显示是不相同的,那么这些在图例中显示系列的图表类型能从独立的图例中获益。

       对于在图例中显示系列的多个图表来说(除了饼图,堆积饼图和圆环图之外的图表),为它们使用同一个图例有一个相当恼人的问题:图表控件在初始化图例时,会为每个图表中每个出现的系列在图例中添加一项。如果您在五个图表中显示两个系列,图表空间图例会包含10个图例项,相同的两项重复了五次。删除额外的图例项的方法和前面提到的一样,可以在设计阶段选择并删除它们,或在代码中使用WCLegendEntry对象的Visible属性。
posted on 2006-06-19 15:33  yiriqing  阅读(948)  评论(0编辑  收藏  举报