chris lovett
2000年10月16日张贴
2000年11月20日存档
你用过 office web 组件吗?最近我经历了一件十分有趣的事 — 在这里介绍给大家,因为我认为它很好地说明了 xml 与面向对象的 api 之间的区别。
我正在编写一些 active server pages (asp) 代码,以便将我们小组修改错误的进度制成图表。我们有一个 sql server 数据库,其中包括所有的错误,这些错误分配给谁来处理、何时打开、解决或关闭它们,以及它们当前的状态。
我们的 sql server 数据库保留的历史记录不足以生成这样的图形,所以我还得创建一个 xml 文件,用于缓存每日对数据库进行查询的结果。这样,根据该 xml 文件,我就可以生成这样的图形。这个 xml 文件也是一个 listeditor(英文)文件,因此可以使用数据库外部的其它信息,如要修改错误的目标数(即上面图表中的黑线),直接对它进行编辑。
该 xml 文件中包括的各项如下所示:
<item>
<id>32</id><date>8/31/2000</date>
<target>146</target><active>167</active>
<dev>69</dev><pm>19</pm><test>1</test><ue>58</ue>
<resolved>484</resolved>
<rdev>15</rdev><rpm>36</rpm><rtest>396</rtest><rue>0</rue>
<in>33</in><out>36</out>
</item>
初次尝试
我研读了 msowcvba.chm 中记录的 office 2000 web 图表组件 api,发现可以通过多种输入源来生成图表,这些输入源包括数组、字符串、记录集和电子数据表。我浏览了那些示例,确定使用数组是最简便的方式。
于是,我编写了一套 asp 代码,用于生成客户端 jscript 代码,以便通过这些数组生成图表。这种 asp 代码如下所示:
<object id=chartspace1 classid=clsid:0002e500-0000-0000-c000-000000000046 style="width:100%;height:350"></object>
<script language=vbs>
sub window_onload()
' 对于不同图表系列要使用的颜色。
dim colors(10)
colors(0) = "black"
colors(1) = "blue"
colors(2) = "red"
colors(3) = "green"
colors(4) = "magenta"
colors(5) = "orange"
colors(6) = "brown"
colors(7) = "gray"
colors(8) = "purple"
colors(9) = "yellow"
colors(10) = "lightgreen"
chartspace1.charts.add
set c = chartspace1.constants
' 创建描述每个系列的字符串的数组。
<% var xpath = "//schema/elementtype/element[@view = '']"
var nodes = doc.selectnodes(xpath);%>
dim series(<%=nodes.length%>)
<%
var series = new array()
var node = nodes.nextnode();
i = 0
while (node != null) {
var name = node.getattribute("type");
if (name != "id" && name != "date") {
series[i] = name;
%>
series(<%=i%>) = "<%=name%>"
<% i++;
}
node = nodes.nextnode();
}%>
' 现在获取各类别的名称。
dim dates()
<% nodes = doc.selectnodes("//item/date");%>
dim categories(<%=nodes.length%>)
<%
k = 0
var node = nodes.nextnode();
while (node != null) {
d = node.text.substr(0,node.text.length-5)
%> categories(<%=k%>) = "<%=d%>"
<%
k = k + 1
node = nodes.nextnode();
}%>
' 现在获取每个系列的值。
<%
var values = new array();
for (j = 0; j < i; j++)
{
name = series[j];
nodes = doc.selectnodes("//item[date]");%>
dim values(<%=k%>)
<%
x = 0
first = true
var node = nodes.nextnode();
while (node != null) {
var child = node.selectsinglenode(name);
if (child && child.text != "") {
values[x] = parseint(child.text);%>
values(<%=x%>) = <%=child.text%>
<%
first = false;
} else if (first) {
values[x] = 0;%>
values(<%=x%>) = 0
<% }
x = x + 1;
node = nodes.nextnode();
} %>
chartspace1.charts(0).seriescollection.add
set chartseries = chartspace1.charts(0).seriescollection(<%=j%>)
chartseries.caption = series(<%=j%>)
chartseries.line.color = colors(<%=j%>)
chartseries.setdata c.chdimcategories, c.chdataliteral, categories
chartseries.setdata c.chdimvalues, c.chdataliteral, values
<% } %>
chartspace1.charts(0).haslegend = true
chartspace1.charts(0).type = c.chcharttypeline
chartspace1.charts(0).axes(c.chaxispositionleft).majorunit = 25
end sub
</script>
我并不特别喜欢这种解决方案,因为维护 asp 代码简直太困难了。我对它做了一些改动,这样它可以生成一个 html 页,将 xml 下载到客户机,并完全在客户端生成图表。这样还能够为我的 web 服务器分担一部分负载。
所有事情都进行得很顺利,但是到了为 api 本身制作图表的时候,我却遇到了巨大的障碍。如果你常常使用 excel 图表,那么你可能看到过一些很棒的组合图表 — 可以在同一图表上显示两条刻度不同的纵轴,如果你仔细观察上文中显示的图表,就会发现这正是我想要实现的。我将图表设定为:线条使用左边的纵轴,其最大刻度为 700;条形则使用右边的纵轴,其最大刻度为 160。结果表明使用 office 2000 web 组件中的图表制作 api 无法生成这样的图表。我被难住了,于是给 office 工作人员发了一封电子邮件,向他们询问是否有什么变通的方法。