** 译者说明: ** 欢迎访问我的 Blog: http://blog.csdn.net/daidaoke2001/
译文中的错误或不当之处望不吝指出, 这也是我坚持翻译工作的最大动力。
我的 Email : [email protected]
如需转载,请事先通知。
** 高级编程技巧 ** ** **
至此,您已经学会了如何完成一些基础的编程操作,现在让我们来讨论一些更高级的技巧。在第七章的销售分析和报表解决方案中会涉及到许多这些高级技巧,因此现在我只对这些技巧作一些简单的介绍,您可以参考第七章,其中有关于本节中所包含的代码的详细解释。
** 保存和恢复视图 ** ** **
任何在报表系统中使用透视表组件的开发者都有可能需要向他们的用户提供如下功能:保存创建的报表视图,并在以后恢复这个报表――但报表中的数据将是最新的数据。透视表控件能够很容易的完成这个任务。在第七章的解决方案中讲述了这种技巧。
最常见的保存和恢复视图的方法是使用控件顶级接口的 XMLData 属性。这是一个读 / 写的属性,它返回一个 XML 格式的庞大的字符串。别将它和用作数据源的 XML 流混淆了―― XMLData 属性返回的是当前视图的布局,格式化,过滤,排序,和等等其它的定义信息。这个定义信息的字符串对视图进行了完整的描述,但是不包含任何数值。
如果需要保存当前视图的定义,应该读取这个属性的值,并将它保存在一个以后您可以重新提取它的地方。一个常用的方法是将这个字符串提交给一个 ASP 页面或 CGI 程序,该页面或程序会接着将这个字符串写入一个文件中,或写入数据库中并与当前用户进行关联。当用户需要再次查看报表时,程序应该从永久存储设备中提取这个字符串,并用它来设置 XMLData 属性。属性被设置后,透视表控件会清除所有当前显示的数据,连接到原始数据源(如果还没有连接到数据源),并执行相应的查询以重新创建报表。因此用户会在报表中看到所有最新的数据,但报表的布局和用户存储报表时完全一样。
对于视图中那些不再有效的部分,透视表控件会简单的丢弃它们。例如,如果在保存视图后,视图中的一个字段集在数据源上被删除了,透视表控件会忽略所保存的与这个字段集有关的任何信息,而不会在视图中尝试恢复它。对于不再包含在查询返回的数据集中的汇总值或成员,也是一样的。
可以运行随书光盘中的 XMLDataProperty.htm 文件来观看如何使用 XMLData 属性。页面顶部的按钮允许您获得 XMLData 属性的值,以及设置这个属性的值。此外,还可以清空透视表报表。请尝试着使用获得属性的值,清空透视表报表,以及重置属性这三个功能。
注意,连接信息(连接字符串,以及 cube 名称或命令文本)也包含在 XMLData 属性返回的字符串中。如果在用户保存报表和重新打开它之间数据源的位置发生了变化,透视表将无法连接到数据源,并产生一个错误。如果可能会发生这种情况,您应该添加错误处理代码来进行捕捉,并在将字符串传递给透视表控件之前调整其中的连接信息。连接字符串是存储在
1<x:connectionstring> 标签中的,数据成员 (OLAP 数据源的 cube 的名称 ) 是存储在 <x:datamember> 标签中的,而命令文本 ( 用于表列数据源 ) 是存储在 <x:commandtext> 标签中的。可以使用 VBScript 或微软 VBA 中的 InStr 和 Replace 函数轻松的查找和替换这些标签的内容。第七章中有关于 XMLData 属性和如何改变数据源的更多信息。
2
3** 锁定视图 ** ** **
4
5报表系统经常需要发布两种类型的报表:一种是每个人都可能需要查看的标准报表,另一种是用户可以修改报表结构,并保存的特殊报表。您可能需要对标准报表进行设置,以便用户不能在报表中删除或添加字段,但仍能够进行钻取和过滤。您也可能需要禁止过滤功能,只允许在视图中进行展开和收缩的操作。透视表组件提供了一些设置选项,可以帮助您锁定视图。它还提供了一些事件,可以用来监控当前用户正在进行什么操作;但是,并不存在禁止这些操作的通用机制。
6
7**XML** ** 历险 ** ** **
8
9所有这些令人惊奇的 XML 的功能都应该归功于另一位 OWC 小组的著名开发者, Kevin Grealish ,他花费了无数个夜晚来研究 xml 解析器,名称空间,以及那些不断变化的格式和标准。当我们开发透视表组件时,关于名称空间的 xml 标准仍然不断的被大幅度的修改。因为我们必须要读取 Excel2000 发布的 XML 数据,所以要使我们的代码处理 xml 的功能与 Excel 保持一致,这是一件艰苦长期的工作。而如果透视表报表的数据源是表格数据,我们的代码还必须与用来装载 Excel 保存的 XML 数据流的 MDAC 永久提供者保持一致。最后 Kevin 解决了这个矛盾――所以下次在您使用 XMLData 属性或使用 XML 作为数据源时,记得要感谢 Kevin 呦。
10
11如果不允许用户在行轴或列轴上添加或删除字段,应该将透视表控件的 AllowGrouping 属性设置为 False 。当该属性为 False 时,透视表控件就会禁止用户在行轴或列轴上添加或删除字段。不过用户仍然可以将字段集添加到过滤轴上,以及将新的汇总值添加到视图中。
12
13如果不允许用户改变任何过滤设置,应该将 AllowFiltering 属性设置为 False 。当这个属性为 false 时,透视表组件允许用户打开过滤下拉列表,但是不允许用户改变当前的过滤设置――换句话说,用户可以看到当前的过滤条件,但不能改变它们。控件还会禁止用户将字段集添加到过滤轴上。
14
15为了保证用户不能改变应用到报表上的格式化信息,可以将 AllowPropertyToolbox 属性设置为 False 。这会使工具条上的属性工具箱按钮,以及相应上下文菜单中的菜单项不可用。这样用户甚至都不能打开属性工具箱了。但是,用户还是可以使用键盘格式化命令,例如 Ctrl-B,Ctrl-I, 和 Ctrl-U 。请查看随书光盘中的 LockDownView.htm 例子文件,以练习这些属性的用法。
16
17** 判断所选择的部分,以进行穿透钻取 ** ** **
18
19和图表组件一样,透视表组件在顶级接口中也有一个 Selection 属性,用来返回当前被选择的对象。而且这个属性返回的对象的类型也是变化的,因此需要使用 VBScript 和 VBA 中的 TypeName 函数来判断返回对象的类型。请运行随书光盘中的 DeterminingSelection.htm 文件以查看透视表控件可以从这个属性返回哪些不同类型的对象。
20
21如果知道当前被选择的是什么,就可以模拟一些有趣的功能。在这里讨论一个这样的功能:通过穿透钻取以获得详细信息。
22
23OLAP 系统善于显示高层的数据摘要,并允许用户通过“向下钻取”来获得各层的详细信息。但是,用户最终会到达超立方体中的最底层,并常常需要“穿透钻取”的功能以获得组成最低层汇总值的下层详细信息。如果当前使用的是一个表列数据源,则透视表控件可以自动完成这个工作,因为在表列数据源的情况下,详细数据总是可用的。但是,对于 OLE DB for OLAP 来说,还没有一种通用方法,可用来提取合计后面的详细信息的集合。尽管如此,垂直解决方案通常都能获得足够的信息,以找出那些包含了详细数据的表列数据源,并从而能够确定应该组成一个怎样的 sql 语句,以获得组成这个合计值所需的所有成员的详细信息数据行。??????。
24
25下面取自随书光盘中 DeterminingSelection.htm 例子文件的代码,显示了如何从被选择的汇总值中获得所需的全部信息,以生成提取汇总值的详细信息的 sql 语句。
26
27Sub PivotTable1_SelectionChange()
28
29' Local variables
30
31Dim sel ' Temporary selection object
32
33Dim sFilters ' Current filter strings
34
35Dim fSet ' Temporary fieldset reference
36
37' Grab the current selection
38
39Set sel = PivotTable1.Selection
40
41' There are many types of objects that the selection
42
43' could be, depending on what was selected
44
45' Examples include PivotAggregates, PivotTotals,
46
47' PivotMembers, PivotFields, and PivotView
48
49' You can use the TypeName function to determine the type
50
51' of the object
52
53'
54
55' If the user selected an aggregate number,
56
57' the TypeName function will return "PivotAggregates"
58
59' Set the type name label
60
61lblType.innerText = TypeName(sel)
62
63' If the type is "PivotAggregates", show how to get
64
65' the row and column members that define that aggregate
66
67' You could of course make this a Select Case statement
68
69' and handle other selection types
70
71If TypeName(sel) = "PivotAggregates" Then
72
73' PivotAggregates could contain many items, but since
74
75' this is a sample, I will just work with the first item
76
77Set pivotagg = sel.Item(0)
78
79' Set the value label
80
81lblVal.innerText = pivotagg.Value
82
83' Get the total caption, the row and column members,
84
85' and the current filters
86
87lblTotal.innerText = pivotagg.Total.Caption
88
89lblColMems.innerText = BuildFullName(pivotagg.Cell.ColumnMember)
90
91lblRowMems.innerText = BuildFullName(pivotagg.Cell.RowMember)
92
93For Each fset In PivotTable1.ActiveView.FilterAxis.FieldSets
94
95sFilters = sFilters & fset.Caption & "=" & _
96
97fset.FilterMember.Caption & ", "
98
99Next
100
101lblFilters.innerText = sFilters
102
103Else
104
105' Selection was something other than a PivotAggregates
106
107' object. Clear the labels.
108
109lblVal.innerText = ""
110
111lblTotal.innerText = ""
112
113lblRowMems.innerText = ""
114
115lblColMems.innerText = ""
116
117lblFilters.innerText = ""
118
119End If 'typename(sel) = "PivotAggregates"
120
121End Sub 'PivotTable1_SelectionChange()
122
123---
124
125这段代码首先使用 TypeName 函数来判断被选择部分的类型;如果类型是 PivotAggregates ,则表明用户选择了一个汇总值。代码就会提取汇总值的数值,以及汇总值所属的合计的值。(规定了一个汇总值只能属于一个合计。)接着,代码使用辅助函数 BuildFullName ,来创建一个包含轴上这一层的所有成员的字符串。 BuildFullName 函数的代码如下:
126
127Function BuildFullName(PivotMem)
128
129' Local variables
130
131Dim pmTemp ' Temporary PivotMember reference
132
133' Start by getting the current member's name
134
135sFullName = PivotMem.Caption
136
137' Set the temporary reference to the current member
138
139Set pmTemp = PivotMem
140
141<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt
142---</x:commandtext></x:datamember></x:connectionstring>