1. 程式人生 > >使用 Office 2000 圖表元件建立服務端圖表

使用 Office 2000 圖表元件建立服務端圖表

你們中的一些人可能已被要求寫那些為不斷變化的資料建立圖表的ASP 頁面。通常的解決方案是要買一個商業服務端圖表生成元件。好,Office 2000中包含一個自身使用的圖表元件 ,並且你不需要載伺服器上安裝整個 Office 或是 Excel  。 而且 ,作為一個動態連結庫(DLL),你不必為了允許元件處理而改變元資料(譯註: 描述資料的資料)。這篇文章將向你介紹如何編寫ASP應用程式,它的功能是從XML檔案接收股票行情 ,並將資料儲存在資料庫中而後建立使用者自定義的圖表。

安裝圖表元件 

  為了安裝服務端元件,需要在伺服器上執行Office2000安裝程式並且選擇安裝Microsoft Office Web Componets。注意你的需要有一份Office2000的許可協議,哪怕不安裝其它的應用(Word、Excel)。 

建立資料庫

  我們要建立一個數據表來存放我們獲得的股票行情 。建立一個  Access  的資料庫叫做 quotes.mdb,包括一個叫做 quotes的表。使用以下圖示的表設計,或者使用本文提供的示 例。
 20001103_1.gif

取得並儲存XML格式的股票行情

股票行情資料來自一個XML檔案,它包括在下載的示例中。我將用微軟的XML格式來儲存XML 檔案,它允許直接載入資料到ADO記錄。如果資料來源存在幾種不同的格式,我們將不得不翻譯 XML 檔案為此格式或是寫一些語法解析程式碼來獲得相關資料。我們用loadxml.asp頁面來完成此功能: 

Dim Stock, Last
file = server.mappath("xmlquote.xml")
objrecordset.open "file://" & ' file open recordset
objrecordset.movefirst
while not objrecordset.eof
  Stock = objrecordset("stock")
  Last = replace(objrecordset("last"), ",", ".")
  data = date()
  Set objRecordSet1 = objDataCon.Execute("INSERT INTO quotes (Stock, Last) VALUES _
  ('" & stock & "', " & last & ") ", lRecordsFound)
  objrecordset.movenext
wend
objrecordset.close

  這個例子是從本地的檔案系統來載入XML檔案,但是更為現實的情況將是從一個Internet伺服器中載入: 

objrecordset.open "http://www.webservername.com/stock/quotes/" & file

  一旦裝載的記錄集同其它的記錄集是一樣的。這段程式碼疊代所有的記錄並在資料庫中載入其值。Replace 函式在我的計算機上是必須使用的,因為我的區域設定中數字的分隔符是逗號不是點。如果XML原始檔也使用點作為數字分隔符則你可不必使用它。

  在一個真實的環境中這個頁面應該假如一個時間表,每隔一點時間呼叫來獲取股票行情的取樣。圖表的精確程度受限於取樣的間隔和其一致性。

  將XML檔案直接儲存為ADO記錄集是ADO2.1的新功能並且在ADO2.5中得到了加強。如果你希望知道更多的ADO 和XML記錄集的資訊,請點選在相關連結中的參考。 

讓使用者來定義圖表

  即時圖表(Just-In-Time)將變得越來越吸引人,特別是使用者能夠定義圖表的引數。這類選項是很多的,我為使用者輸入選擇了三個引數: 

  • 日期間隔(起迄日期)
  • 圖表的大小(寬、高)用象素表示 
  • 標股票(多重選擇)

  更多的選包括圖的型別(line,bars,etc),式樣 (2D、3D)並且幾乎是和Excel圖表嚮導中的一樣多。這些值在default.asp頁面中被使用者輸入,並在下面的作圖頁面quotes.asp 中被顯示。 

20001103_2.gif

  日期範圍是自動地根據可用股票行情的時間跨度進行調整的,並且股票列表是動態的從行情 資料庫中生成的。 

生成圖表

  我們一旦讓使用者做出選擇,我們就能生成相應的圖表。quotes.asp頁面讀取傳送的引數並分三步生成圖表: 

 建立物件並設定全域性屬性 

  圖表物件支援多個圖,其中每一個都是一個物件。在這個頁面中我們僅僅需要一個。一些全 局屬性屬於繪製物件,但大多數用來設定圖表本身。有很多的屬性可以使用,下面僅是我選擇的:

' Create a Chart Object
Set oChart = Server.CreateObject("OWC.Chart")
Set c = oChart.Constants 'object with charting constants

' Set the different parameters for the ChartSpace
oChart.Border.Color = c.chColorNone

' Add chart object and define its type (line)
Set Chart = oChart.Charts.Add
Chart.Type = oChart.Constants.chChartTypeLine
Chart.HasLegend = True
Chart.HasTitle = False
Chart.Legend.Position=oChart.Constants.chLegendPositionBottom

 載入資料值

  每一個圖表都有幾種資料值集合,表現為不同的線段。每一個股票是一個值集並且所有的值 集共享一個定義好的日期範圍。這組值通過已經建立的陣列載入。此陣列從資料庫中生成。 自然我們不知道將來的陣列中會包含多少的元素,所以不得不建立動態陣列,並根據從讀數 據庫中讀取的資料改變大小: 

' Add a value set for the chart
Set Serie = Chart.SeriesCollection.Add
Serie.Caption = stock 'parameter, stock name
' Load x朼xis labels
Serie.SetData c.chDimCategories, c.chDataLiteral, Categories 
' Load values
Serie.SetData c.chDimValues, c.chDataLiteral, Vals

 儲存圖表為一個GIF檔案

  一旦所有的資料被載入,圖表已準備好生成。輸出必須被加入到迴應頁面,為了這樣做圖表 要被儲存為一個唯一名字的GIF檔案。而回應頁面應包括一個該影象的連結: 

' Get a temporary filename to save chart in that file
' The filesystem object is already open

sFname = FS.GetTempName & session.SessionID & ".gif"

' Export the chart to the temporary file (width and height from user parameters)
oChart.ExportPicture server.MapPath(sFname), "gif", cint(wchart), cint(hchart)

' Create a link to the generated file
Response.Write "<center><img src='" & sFname & "'></center>"

' Destroy objects 
set fs = nothing
set oChart = nothing
set Chart = nothing
set Series = nothing
set c = nothing

臨時檔案的刪除

  你現在有了即時圖表,但是但是也留下了很多的臨時檔案。每次使用者建立一個圖表 ,一個臨時檔案就會留在硬碟上,不再被使用。一種解決方案是建立另一個asp頁面來刪除這些檔案,但是這要求一個排程機及時地啟用此頁面。

  我的方案是例用繪圖頁面自身。每次一個使用者要求一張圖時,頁面首先刪除超過一分鐘的老檔案。此函式如下:

Sub DeleteOldCharts()
' Delete temporary files older than one minute
on error resume next
Dim fileSystem, File, File1, FileColl, s
Dim cnt, globalcnt, fname
dim path, dir

   file = "charts.asp" 'Use the page own filename
   path = server.mappath(file)
   dir = left(path,len(path)杔en(file))

Set filesystem = server.CreateObject("Scripting.FileSystemObject")
Set file = filesystem.GetFolder(dir)
Set filecoll = file.Files    

cnt = 0: globalcnt = 0
For Each file1 in filecoll
   filedate = file1.datecreated
   globalcnt = globalcnt + 1
   if timevalue(filedate) < timevalue(dateadd("m",?,now())) then
      fname = file1.name
      if instr(ucase(fname), ".GIF") then
         filesystem.deletefile dir & fname, true
         cnt = cnt + 1
      end if
   end if
Next

Set filesystem = nothing
Set file = nothing
Set filecoll = nothing

End Sub

  一分鐘的間隔足以避免刪除正在使用中的檔案,不過你也可以根據需要增加時間間隔。這個方案會將一些檔案同時留在硬碟上,但有效的阻止了硬碟空間佔用的無限增長,使其保持在一個可以接受的水平。

可能的改進

  這個示例應用只是一個起點。凡是瞭解Excel圖表的人都知道,Office2000的圖表元件是一個有著許多屬性和方法的複雜物件,瀏覽它的文件資料是值得的。

  • 不要為每個X軸的值設定標籤:如果取樣值大於圖表的大小,X軸將會不可讀。解決辦法是使用選定的值來設定標籤,並使用固定的間隔。
  • 為多重選擇的圖表定義Y軸的範圍:繪製圖表的例子程式碼中設定Y軸的範圍為一個股票圖表使用的合適的間隔。如果你需要多個股票的圖表則Y軸的範圍要設定為從零到這組資料中的最大值。這樣做看起來像是圖表元件中的一個bug。此方案是直接在程式碼中設定Y軸的最小值和最大值。

示例程式

  包括在本篇文章中的例子,由以下的檔案組成:

  • Default.asp 預設的頁面,使用者引數入口表單
  • Quotes.asp 圖表生成頁面
  • Fuctions.inc 共享的函式庫,所有的ASP頁面都調入此頁
  • Loadxml.asp 載入XML格式的股票行情到資料庫
  • Quotes.mdb Access2000資料庫存放股票行情
  • Xmlquotes.asp 一個XML行情檔案

  為了使用此例子,請在IIS的根目錄下任何位置建立一個資料夾,並將所有檔案複製到此目錄。不需要任何調整或設定ODBC DSN。

概要

  我希望我能夠展示如何利用MS Office 2000圖表元件來輕鬆建立強大的繪製圖表的應用程式。如果你擁有一份Office 2000 或是Excel的許可協議,那麼它和其他可用的圖表元件一樣用途繁多。