指令碼中心指南:ActiveX 控制項

ActiveX 控制項

在您的 HTA 新增直條圖

其他 ActiveX 控制項

您是不是有過在觀看某位主管做簡報時,邊看邊想:「哇,這些直條圖實在太酷了,真希望把它們加入我的系統管理指令碼中」的經驗。肯定有過吧,畢竟我們也曾經是其中的一員嘛。絞盡腦汁做出的圖表,竟然是為了呈現那些營業利益和每股盈餘等等無聊的資料:啊,真是夠了!在最後這篇 ActiveX 控制項週刊當中,我們要把直條圖從張牙舞爪的 PowerPoint 魔掌中解救出來。這種崇高的理想一聽就知道是不可能的任務對吧?沒有朋友,光有 Office XP (或更新的版本) 和滿腔熱血,什麼都做不成。好了,沒時間浪費了,趕緊導入正題,看看如何在 HTA 使用 Office Web Components ChartSpace (英文) 控制項吧。

若要在 HTA 使用圖表控制項,請先插入下面這個 <object> 標籤:

<object id=objChartSpace classid=CLSID:0002E556-0000-0000-C000-000000000046></object>

此舉有兩個作用。它會建立一個「圖表空間」物件,並且指定 objChartSpace 作為名稱,稍後您要使用這個物件時,就可以使用這個名稱。當您發現我們建立的竟然是圖表「空間」,而不是圖表時,應該很訝異吧,不過到了下個步驟就不會這麼訝異了:將圖表加入剛造好的圖表空間。

如果您還是覺得有必要思考一下「圖表空間」,別把它想得太抽象,只要把它想成您可以放置圖表的地方就行了。

Set objChart = objChartSpace.Charts.Add

那我們就試試看吧。請將下面這個程式碼儲存在一個檔案中,以 .HTA 作為副檔名,然後再按兩下該檔案。

<html>

<head>
<title>Chart Control - Hard Drive Space</title>
</head>

<body>

<object id=objChartSpace classid=CLSID:0002E556-0000-0000-C000-000000000046></object> 

<script language=vbscript>

Set objChart = objChartSpace.Charts.Add
 
</script>


</body>
</html>

接著會出現下面這個圖形。看起來像是一個漏了直條的直條圖。

HTA 螢幕擷取畫面

好,接著請選取 HTA 視窗,然後按幾次 F5 將它重新整理。下面就是重新整理 25 次之後所出現的畫面。其實您不必重新整理到 25 次也能一窺究竟,不過這麼做也挺有意思的啦。

HTA 螢幕擷取畫面

每次您重新整理 HTA 時,我們都會呼叫下面這行程式碼,加入一個新圖表。

Set objChart = objChartSpace.Charts.Add

雖然我們是希望在 HTA 中顯示更多圖表,但我們必須控制在新增每張圖表,而不是每次重新整理視窗時,顯示一張新圖表。因此,下面我們所介紹的程式碼,會檢查圖表空間中的圖表數目,只有在沒有任何圖表的情況下,才容許加入一張新圖表。

If objChartSpace.Charts.Count = 0 Then
   Set objChart = objChartSpace.Charts.Add
End If

多了這層檢查,您就可以盡情的重新整理 HTA,而且只會看到一張圖表出現:看清楚了,這張圖表的座標軸上沒有標題、標籤,也沒有我們在直條圖上習慣看到的美美的直條。

算了,這種小缺點,我們就別太在意吧。接下來我們要利用下面這個程式碼,在圖表加上標題。

objChartSpace.Charts(0).HasTitle = True
Set objTitle = objChartSpace.Charts(0).Title
objTitle.Caption = "Hard Disk Usage"
objTitle.Font.Bold = True
objTitle.Font.Name = "Helvetica"
objTitle.Font.Size = 12

請注意第一行。您必須確實指定圖表標題之後,才能使用這個標題。您會從圖表 0 的 Title 屬性取得 Title 物件 (就是您加到圖表空間的那一千零一張圖表),將它儲存在 objTitle 變數。

在本文結束之前,我們會在圖表直條顯示電腦硬碟上可用空間的相關資訊。因此我們要將圖表標題設為 Hard Disk Usage。我們是藉由設定標題的 Caption 屬性,來達到這個崇高的目標。接著就設定標題的字型。如需 Title 物件 (及其字型、框線和內部子物件) 的詳細資訊,請參閱此處 (英文) 的 MSDN 文件。

下面就是到目前為止,我們 HTA 程式碼的樣子:

<html>

<head>
<title>Chart Control - Hard Drive Space</title>
</head>

<body>

<object id=objChartSpace classid=CLSID:0002E556-0000-0000-C000-000000000046></object> 

<script language=vbscript>


If objChartSpace.Charts.Count = 0 Then
   Set objChart = objChartSpace.Charts.Add
End If


objChartSpace.Charts(0).HasTitle = True
Set objTitle = objChartSpace.Charts(0).Title
objTitle.Caption = "Hard Disk Usage"
objTitle.Font.Bold = True
objTitle.Font.Name = "Helvetica"
objTitle.Font.Size = 12


</script>


</body>
</html>

而下面則是執行中的 HTA:

HTA 螢幕擷取畫面

好,除了直條之外,直條圖最令人印象深刻的東西,就屬顯示在每個圖表軸上,經過精心挑選的標籤了。現在我們要畫一道直線,代表一組電腦上已用的磁碟空間百分比。因此,我們需要將垂直軸的標籤設為 % Used Disk Space,將水平軸的標籤設為 Computer。我們只要將下面這個程式碼直接插在標籤碼後面,就能完成這道程序了:

Set objAxis = objChartSpace.Charts(0).Axes(0)
objAxis.HasTitle = True
objAxis.Title.Caption = "Computer"
objAxis.Title.Font.Size = 8
objAxis.Title.Font.Bold = True

Set objAxis = objChartSpace.Charts(0).Axes(1)
objAxis.HasTitle = True
objAxis.Title.Caption = "% Used Disk Space"
objAxis.Title.Font.Size = 8
objAxis.Title.Font.Bold = True

再次強調,我們必須明確指定要在每一個座標軸加上標題,這一點就借助程式碼 objAxis.HasTitle = True 辦到。哇!您看看,我們的直條圖越來越有型了,差不多有那位主管的水準了。接下來再填上薪資資料就大功告成了。

HTA 螢幕擷取畫面

我們想要呈現已用磁碟空間的百分比。但是,該圖表的調整比率是以 0.2 的增量,從 0 增加到 1.2,這可不容易。我們必須把它改為 0 到 100 才行 (增量則視圖表控制項而定)。下面就是調整垂直軸的程式碼:

Set objScale = objChartSpace.Charts(0).Axes(1).Scaling
objScale.Minimum = 0
objScale.Maximum = 100

而下面則是到目前為止執行中的 HTA:

HTA 螢幕擷取畫面

完成所有例行設定工作之後,接下來就要收集有用的資料,賦予它生命。不過,該做的事還是要先做:如果您不熟悉 WMI 指令碼,請先停在這裡,看看這個 Scripting Week 1 網路廣播 (英文) 。

好,我們已經從 WMI 獲得充份的資訊,接下來就要專注在一個範例了:關於 Win32_LogicalDisk 類別的磁碟空間資訊。如果您這個禮拜一直不知道該做什麼事,現在不必猶豫了:您可以像 Scripting Guy 一樣,試試將其他 WMI 類別提供的有用資料,以圖表呈現。

等到要在圖表控制項提供資料時,必須將這些資料以陣列格式表示。其實我們需要兩個陣列 - 一個包含所有我們擷取資料的來源電腦名稱,另一個包含對應的 WMI 資料 (已用磁碟空間的百分比)。

下面這一小段程式碼的目的,就是從陣列 arrComputers 中的每一部電腦擷取 WMI 資料。如果您想學習如何從 Active Directory 或文字檔擴展這樣的陣列,而不只是打打字而已,請看看取自 Scripting Week III (英文) 的這個網路廣播。

arrComputers = Array("atl-ws-01","atl-ws-02","atl-ws-03","atl-ws-04")
strTmp = ""
For Each strComputer in arrComputers
   Set objWMIService = GetObject("winmgmts:\\" & strComputer)
   Set colDiskInfo = objWMIService.ExecQuery _
      ("SELECT FreeSpace,Size FROM Win32_LogicalDisk WHERE deviceid='c:'")
   For Each objDiskInfo In colDiskInfo
      iPercentageFreeSpace = (objDiskInfo.Size - objDiskInfo.FreeSpace)/(objDiskInfo.Size)*100
      If strTmp = "" Then
         strTmp = iPercentageFreeSpace
      Else
         strTmp = strTmp & "," & iPercentageFreeSpace
      End If
   Next
Next

arrValues = Split(strTmp,",")

在絕大多數的情況下,這都是相當標準的 WMI 指令碼 - 與 Scriptomatic (英文) 所寫的很類似。不過,還是有一些地方與您的習慣不同。首先,這個類別沒有 PercentageUsedSpace 屬性;不過,它倒是提供了我們計算該值所需的資訊。這就是下面這行程式碼所要做的:

iPercentageFreeSpace = (objDiskInfo.Size - objDiskInfo.FreeSpace)/(objDiskInfo.Size)*100

第二,在前面提過,我們要把結果累積在陣列中。做法是以逗號 (,) 區隔每部電腦傳來的結果。等所有電腦的資料都收集完畢之後,就開始分配以逗號區隔的結果,將它們儲存在一個名為 arrValues 的陣列中。

接下來,您可能會納悶為什麼要用到下面這個 If..Then..Else 迴圈:

If strTmp = "" Then
    strTmp = iPercentageFreeSpace
Else
    strTmp = strTmp & "," & iPercentageFreeSpace
End If

這是因為我們不要把逗號 (,) 插在第一筆 WMI 資料前面。因此,如果變數 strTmp 是空的,我們就知道這是第一次執行迴圈,不必加逗號。

現在我們有兩個需要用到的陣列:arrComputers 存放電腦名稱,而 arrValues 存放對應的已用磁碟空間百分比值。

最後一步就是將這兩個陣列代入圖表控制項。這就是下面這段程式碼所做的動作:

Set objConstants = objChartSpace.Constants
objChartSpace.Charts(0).SeriesCollection(0).SetData _
    objConstants.chDimCategories, objConstants.chDataLiteral, arrComputers
objChartSpace.Charts(0).SeriesCollection(0).SetData _
    objConstants.chDimValues, objConstants.chDataLiteral, arrValues

關於這個程式碼,您有兩點必須注意。首先,第一行的目的是建立一個負責傳回常數值的物件。因此,Set objConstants = objChartSpace.Constants 會建立一個 ‘constants’ 物件,並且將其參考儲存在 objConstants 變數中。稍後,再利用像 objConstants.chDataLiteral 這樣的呼叫,擷取您必須記住的值。

第二件要注意的,是使用 SetData 方法的那兩行,都各自參考一個 SeriesCollection。我們還沒有在圖表中加入其中一個,所以現在一定要加入。等將圖表加到圖表空間之後,就立刻將 SeriesCollection 加到圖表中。

If objChartSpace.Charts.Count = 0 Then
   Set objChart = objChartSpace.Charts.Add
   objChart.SeriesCollection.Add
End If

下面這行使用 SetData 的程式碼,會指定 chDimCategories 常數,告訴 Chart 物件擷取代入陣列 (arrComputers) 中的值,將它們在直條圖中的每一個直條下方,顯示為 ‘categories’。

objChartSpace.Charts(0).SeriesCollection(0).SetData _
    objConstants.chDimCategories, objConstants.chDataLiteral, arrComputers

下一個使用 SetData 的程式碼,則指定 chDimValues 常數,告訴 Chart 物件擷取代入陣列 (arrValues) 中的值,將那些值在圖表中以長條表示:

objChartSpace.Charts(0).SeriesCollection(0).SetData _
    objConstants.chDimValues, objConstants.chDataLiteral, arrValues

在這兩種情況中,chDataLiteral 值會指出陣列所提供的資料就是實際要用的值,而不呈現計算數值或任何類似數值之內容的函數。

下面這個螢幕擷取畫面,就是最後的 HTA。雖然最初所定的目標是崇高了點,我們到底還是達到了:沒有任何重點提示,倒是有感動人心的 WMI 音效在背景迴盪。什麼?您聽不到 WMI?我們以為大功告成了,現在看來好像還得再寫一篇 Scripting Week IV。如果您要進一步鑽研 Chart 物件的功能,不妨從MSDN (英文) 著手。謝謝您跟我們一起參與 ActiveX 控制項週 - 可別浪費這個禮拜哦。好好利用時間,撰寫一些既好用又好看的 HTA。

HTA 螢幕擷取畫面

下面就是完整的 HTA 程式碼:

<html>
<head>
<title>Chart Control - Hard Drive Space</title>
</head>

<body>

<object id=objChartSpace classid=CLSID:0002E556-0000-0000-C000-000000000046 
style="width:100%;height:100%"></object> 

<script language=vbscript>

If objChartSpace.Charts.Count = 0 Then
   Set objChart = objChartSpace.Charts.Add
   objChart.SeriesCollection.Add
End If

objChartSpace.Charts(0).HasTitle = True
Set objTitle = objChartSpace.Charts(0).Title
objTitle.Caption = "Hard Disk Usage"
objTitle.Font.Bold = True
objTitle.Font.Name = "Helvetica"
objTitle.Font.Size = 12


Set objAxis = objChartSpace.Charts(0).Axes(0)
objAxis.HasTitle = True
objAxis.Title.Caption = "Computer"
objAxis.Title.Font.Size = 8
objAxis.Title.Font.Bold = True

Set objAxis = objChartSpace.Charts(0).Axes(1)
objAxis.HasTitle = True
objAxis.Title.Caption = "% Used Disk Space"
objAxis.Title.Font.Size = 8
objAxis.Title.Font.Bold = True

Set objScale = objChartSpace.Charts(0).Axes(1).Scaling
objScale.Minimum = 0
objScale.Maximum = 100


arrComputers = Array("atl-ws-01","atl-ws-02","atl-ws-03","atl-ws-04")
strTmp = ""
For Each strComputer in arrComputers
   Set objWMIService = GetObject("winmgmts:\\" & strComputer)
   Set colDiskInfo = objWMIService.ExecQuery _
      ("SELECT FreeSpace,Size FROM Win32_LogicalDisk WHERE deviceid='c:'")
   For Each objDiskInfo In colDiskInfo
      iPercentageFreeSpace = (objDiskInfo.Size - objDiskInfo.FreeSpace)/(objDiskInfo.Size)*100
      If strTmp = "" Then
         strTmp = iPercentageFreeSpace
      Else
         strTmp = strTmp & "," & iPercentageFreeSpace
      End If
   Next
Next

arrValues = Split(strTmp,",")

Set objConstants = objChartSpace.Constants
objChartSpace.Charts(0).SeriesCollection(0).SetData _
    objConstants.chDimCategories, objConstants.chDataLiteral, arrComputers
objChartSpace.Charts(0).SeriesCollection(0).SetData _
    objConstants.chDimValues, objConstants.chDataLiteral, arrValues

</script>


</body>
</html>