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