您好,腳本專家! Excel 使用竅門
上月一直在澳大利亞生活和工作,當地同事的創造力和充沛精力總是讓我大開眼界。幾天前,那里的一個朋友帶我和妻子一起外出就餐。他說餐館離我們的酒店僅幾步之遙。
四十分鐘后,我們到達了一個非常漂亮的餐館,此處可眺望悉尼港,悉尼歌劇院熠熠生輝,宛如嵌入五彩沙灘的一枚貝殼。海港大橋(世界上最長的單跨橋)張開結實的臂膀挽起兩側的半島。
返回時,40 分鐘的徒步之行并非一次短暫的閑庭漫步。而是之前需要 15 分鐘熱身和伸展運動的日常鍛煉。
我之所以喜歡此次澳大利亞之行,原因之一是那里的同事看待問題的視角不同。他們的方法似乎別出心裁,常常與我的常規邏輯相悖。
在腳本編寫領域,如果您頭腦中抱定“經試用正確”這一方法,就極易變得墨守成規。很多時候,您切實希望看到的就是使用相同的方法獲取相同的結果。
以監控為例,通過使用 Windows PowerShell,可輕松地獲取本地計算機上進程使用情況的出色快照。利用 Get-Process cmdlet,您會得到條理清晰的輸出,如圖 1 所示。
圖 1 使用 Get-Process 查看本地進程
Get-Process cmdlet 的結果在大部分場合都非常有用。它們顯示了處于打開狀態的句柄數量、各種內存占用視圖以及 CPU 使用率的快照。當 Windows PowerShell 2.0 推出后,您甚至可以使用 Get-Process 和 –computername 參數從遠程計算機檢索這一概述信息。既然有這些好處,那么究竟為什么有人會不厭其煩地研究其他產品?
問題在于冗長的數據背后隱藏著大量細節。數據往往隱藏的是更為重要的細節。盡管將來 Windows PowerShell 2.0 會支持 –computername 參數聽起來令人振奮,但目前它對網絡管理員而言還是海市蜃樓。因此,我們不得不使用 Windows 管理規范 (WMI) 和 Win32_Process WMI 類來監視遠程系統并以實用方式顯示信息。如果認為 Get-Process 的輸出內容非常豐富,請再仔細看看 Win32_Process 的輸出(如圖 2 所示)。
圖 2 利用 WMI 查看進程#p#
那么,如果網絡管理員需要的是易于閱讀的內存占用量報告,這可憐的家伙該怎么辦呢?這正是您需要打破慣例思考、走出自己的圈子并轉用 Excel 實現自動操作的地方。很可能您的計算機上已安裝了 Microsoft Office Excel。可能您像我們一樣并非專家,但由于它是 Microsoft Office 系統的組件,所以也可以利用它。
自動化 Excel 有多難?實際上非常簡單,因為 Microsoft 已創建了專門用于處理 Excel 的自動化模型。程序 ID 是 Excel.Application,它是一個 COM 對象。創建 Excel.Application 對象的實例時,Excel 會默認啟動并運行,只是您看不見它。但是,可使用 visible 屬性讓 Excel 顯示出來。
以下代碼顯示了如何創建 Excel.Application 對象、查詢 visible 屬性的狀態,然后將 visible 屬性設為 true:
PS C:\> $excel = New-Object -ComObject Excel.Application PS C:\> $excel.Visible False PS C:\> $excel.Visible = $true
然后,您會看到一個非常奇怪的 Excel 視圖,它看起來就像 Excel 應用程序的一個外殼(如圖 3 所示)。沒有工作簿、沒有電子表格—只是光禿禿的 Excel。
圖 3 光禿禿的 Excel—沒有工作簿或電子表格
我們需要將一個工作簿添加到應用程序中。為此,我們借助工作簿對象的 add 方法。工作簿對象是從主 Excel.Application 對象進行訪問的,正如您在此看到的,我們將工作簿對象存儲在一個名為 $workbook 的變量中:
$workbook = $excel.Workbooks.add()
現在,需連接特定的電子表格。默認情況下,工作簿添加到 Excel 時,會向其中添加三個電子表格。這些電子表格可通過數字進行標識。在以下代碼行中,連接***個電子表格并將返回的電子表格對象存儲在名為 $sheet 的變量中:
$sheet = $workbook.worksheets.Item(1)
現在,可將數據寫入該電子表格。Excel 電子表格中的信息存儲在單元格中。由于單元格位于電子表格之中,所以可使用 $sheet 變量中存儲的電子表格對象訪問特定的單元格。具體方法是使用指代電子表格中行和列的數字。在 Excel 電子表格中,行是數字而列是字母,這一點有些讓人迷惑。但使用自動化模型時,行和列均為數字。***個數字是行,第二個數字是列。只需對特定單元格進行賦值即可寫入單元格:
$sheet.cells.item(1,1) = "Test"
向 Excel.Application 對象添加一個工作簿并將數據添加到電子表格中的單元格后,Excel 工作簿將如圖 4 所示。
圖 4 向單元格添加值
了解這些內容后,讓我們整理出有用的內容。從 WMI 獲取進程信息集合,將每個進程的名稱和內存占用量寫入 Excel 電子表格,然后創建一個圖表來突出顯示所用內存。這正是 WriteProcessInformationToExcel.ps1 的功能所在。《TechNet 雜志》網站上有完整的腳本。
腳本首先使用 Get-WmiObject cmdlet 檢索有關進程的信息集合。使用 Win32_Process WMI 類獲取該信息,并將其存儲在 $processes 變量中:
$processes = Get-WmiObject -class Win32_Process
現在,創建 Excel.Application 對象的一個實例并將其存儲在變量 $excel 中,然后顯示應用程序并添加一個工作簿。通常,決定執行的任意 Excel 自動化都要完成以上步驟。具體代碼如下:
$excel = new-object -comobject excel.application $excel.visible = $true $workbook = $excel.workbooks.add()
Excel 的一個不足是工作簿始終會創建三個電子表格。我們認為這一點非常浪費,因為我們僅使用一個電子表格。幸運的是,可利用自動化刪除多余的電子表格:使用工作表集合連接第三個電子表格并調用 delete 方法。執行相同的操作刪除第二個電子表格:
$workbook.workSheets.item(3).delete() $workbook.WorkSheets.item(2).delete()
接下來,重命名剩余的電子表格。這一點非常重要,因為如果決定使用 ActiveX 數據對象 (ADO) 來查詢 Excel 電子表格,將在連接字符串中使用此電子表格名稱。因此,要使代碼易讀且直觀,電子表格應具有邏輯名稱。要重命名電子表格,只需向特定電子表格的 name 屬性賦一個值即可。以下代碼將***個電子表格重命名為 "Processes":
$workbook.WorkSheets.item(1).Name = "Processes"
現在,需連接重命名后的電子表格。使用工作表對象的 Item 方法并將電子表格的名稱指定給它:
$sheet = $workbook.WorkSheets.Item("Processes")
電子表格的***行將包含標頭信息。我們將繪制邊框并使屬性名稱顯示為粗體。由于數據將從第二行開始,因此我們將值 2 賦給計數器變量 $x:
$x = 2
接下來的四行代碼創建四個枚舉類型。枚舉類型用于告訴 Excel 允許將哪些值填入特定的選項類型。例如,xlLineStyle 枚舉用于確定所繪制線條的類型:雙線條、虛線等。MSDN 上詳細介紹了這些枚舉值。
為使代碼更易于閱讀,針對將使用的每個枚舉類型創建一個快捷別名。實際上,我們將把代表枚舉名稱的字符串轉換成 [type]。此技術實際是一個非常酷的竅門:
$lineStyle = "microsoft.office.interop.excel.xlLineStyle" -as [type] $colorIndex = "microsoft.office.interop.excel.xlColorIndex" -as [type] $borderWeight = "microsoft.office.interop.excel.xlBorderWeight" -as [type] $chartType = "microsoft.office.interop.excel.xlChartType" -as [type]
現在需格式化***行。使字體為粗體,將線條定義為 xlDashDot,允許自動指定顏色,并將邊框寬度設為中等粗細:
For($b = 1 ; $b -le 2 ; $b++) { $sheet.cells.item(1,$b).font.bold = $true $sheet.cells.item(1,$b).borders.LineStyle = $lineStyle::xlDashDot $sheet.cells.item(1,$b).borders.ColorIndex = $colorIndex::xlColorIndexAutomatic $sheet.cells.item(1,$b).borders.weight = $borderWeight::xlMedium }
完成后,通過使用 item 方法選擇單元格并指定行和列的坐標,向***行賦值。接下來,使用直接賦值寫入列標題:
$sheet.cells.item(1,1) = "Name of Process" $sheet.cells.item(1,2) = "Working Set Size"
現在,需將 WMI 查詢產生的 $processes 變量中存儲的進程信息放入適當的單元格中。使用 foreach 語句遍歷進程信息集合。將變量 $process 定義為集合枚舉器(占位符),并選擇將名稱和 workingSetSize 屬性分別寫入***列和第二列。
$x 變量將在此發揮作用。從第二行開始,在遍歷進程集合的同時,遞增 $x 變量的值以便它始終指向集合中的當前行。通過以下代碼,即可對 $processes 進程信息集合中存儲的所有數據進行整理分類:
Foreach($process in $processes) { $sheet.cells.item($x, 1) = $process.name $sheet.cells.item($x,2) = $process.workingSetSize $x++ } #end foreach
填寫完 Excel 電子表格后,我們打算調整列的大小以使單元格與其中所存儲數據的尺寸相同。為此,可通過指定要使用的列坐標來創建一個范圍;但是,也可以只使用電子表格的 usedRange 屬性。創建完范圍對象后,選擇 EntireColumn 屬性并使用 AutoFit 方法調整列的大小。由于該方法始終會返回數據,我們將結果傳送給 Out-Null cmdlet。從而避免控制臺上布滿了雜亂無用的信息。下面是所用的代碼:
$range = $sheet.usedRange $range.EntireColumn.AutoFit() | out-null
至此我們已經完成了任務,此時的電子表格具有所有進程的名稱和內存工作集,相當不錯。但讓我們繼續創建一個圖表。具體操作非常簡單。使用工作簿的 charts 對象的 add 方法。由于該方法還會返回我們并不想要看到的信息,所以將結果傳給 Out-Null cmdlet,如下所示:
$workbook.charts.add() | out-null
以上命令添加了一個直線圖。如果想要定義另一類型的圖表,需使用一個圖表類型枚舉值。為此,可使用一個 microsoft.office.interop.excel.xlChartType 枚舉值,如 xl3DPieExploded 類型。毫無疑問,xl3DPieExploded 類型將創建一個分裂的三維餅圖。將這一枚舉類型賦給 ActiveChart 對象的 chartType 屬性。然后,將圖表的數據源指定為 $range 變量中定義的范圍。結果是線圖閃爍一下,然后 3D 餅圖在屏幕上爆炸開來。以下是相關代碼:
$workbook.ActiveChart.chartType = $chartType::xl3DPieExploded $workbook.ActiveChart.SetSourceData($range)
在玩耍時,我們想要旋轉餅圖。具體實現方法是使用 ActiveChart 對象的 rotation 屬性。使用 for 語句以 15 為增量將其數量逐漸增加到 360。360 是圓圈的度數;圖表將以每次 15 度的增量旋轉一整圈。實際視覺效果相當酷。以下是實現這一功能的代碼:
For($i = 1 ; $i -le 360 ; $i +=15) { $workbook.ActiveChart.rotation = $i }
***需要做的一件事是保存電子表格。為此,使用 Test-Path cmdlet 查看電子表格是否已存在。如已存在,使用 Remove-Item cmdlet 刪除舊的電子表格,然后將當前的工作簿保存到 $strPath 變量中存儲的位置。使用 Excel.Application 對象的 ActiveWorkbook 對象以及 SaveAs 方法保存工作簿。如果并未保存有電子表格的副本,使用 ActiveWorkbook 對象的 SaveAs 方法并直接保存:
IF(Test-Path $strPath) { Remove-Item $strPath $Excel.ActiveWorkbook.SaveAs($strPath) } ELSE { $Excel.ActiveWorkbook.SaveAs($strPath) }
運行腳本時,您將看到如圖 5 所示的圖表。
圖 5 按進程分裂的餅圖
電子表格本身位于 Processes 選項卡。圖 6 顯示了列標題、針對邊框選擇的點劃線樣式以及粗體列標題。進程名稱和工作集大小屬性是我們顯示的兩列數據。
圖 6 完成后的電子表格
正如您所看到的,通過使用 Excel.Application 自動化模型,即可利用這一功能豐富且強大的應用程序的分析和圖表工具來處理服務器的數據。
Ed Wilson 是 Microsoft 的高級顧問,也是知名的腳本專家。他還是 Microsoft 認證培訓師,為世界各地的 Microsoft Premier 客戶組織召開了廣受歡迎的 Windows PowerShell 研討會。他自己撰寫了八部著作,其中有多本探討了 Windows 腳本,并與人合著了十余部其他書籍。Ed 擁有 20 多個行業證書。
Craig Liebendorfer 是語言藝術家,也是 Microsoft Web 的資深編輯。Craig 一直無法相信他可以每天靠舞文弄墨來維持生計。無厘頭式的幽默是他的***之一,因此他應該非常適合這個工作。Craig 認為美麗動人的女兒是自己一生***的成就。
原文 | 來源:微軟TechNet中文站