Powershell針對Excel的一些簡單操作
稍微高級點的語言都會涉及到對COM對象的操作,作為微軟自己進化的腳本語言,powershell有這個功能一點不稀奇,首先它使用 .NET Framework 提供的強大類庫,很多特性和C#相似;其次,雖然作為腳本但它面向對象。使用powershell來管理WMI和COM更簡單。
用微軟官方的話概括powershell就是:
Windows PowerShell™ 是一種基於任務的命令行 shell 和腳本語言,專門用於管理系統。 Windows PowerShell™ 構建於 .NET Framework 之上,能夠幫助 IT 專業人員和高級用戶控制和自動管理 Windows 操作系統以及在 Windows 上運行的應用程序。
內置 Windows PowerShell 命令(稱為 cmdlet)可用於通過命令行管理企業中的計算機。使用 Windows PowerShell™ Provider,您可以像訪問文件系統那樣輕松地訪問數據存儲,如注冊表和證書存儲。 此外,Windows PowerShell™ 還具有一個功能豐富的表達式分析程序和一種經過充分開發的腳本語言。
下面介紹powershell對excel的簡單操作。
首先,我執行一條命令來獲取系統當前正在運行的所有進程:
Get-Process cmdlet顯示當前本地進程運行狀態,包括處於打開狀態的句柄數量、各種內存占用視圖以及 CPU 使用率的快照。powershell和Linux shell一個很大的不同點就是大小寫不敏感,無論是系統函數還是命令。這點可以減少犯錯的概率。
您可能疑惑為什么講這個?對於系統管理員來說,冗長的數據背后隱藏着大量細節,get-process是獲取本地進程運行情況,當然加上-computername參數后可以訪問遠程計算機,但目前這個對於網絡管理員來說猶如海市蜃樓,所以不得不使用windows WMI和 Win32_Process WMI 類來監視遠程系統並以實用方式顯示信息。如果認為 Get-Process 的輸出內容非常豐富,請再仔細看看 Win32_Process 的輸出:
很明顯,這個輸出很詳細,但是可讀性不強,管理員需要的是易於閱讀的內存占用量報告。可以轉用Excel實現自動操作。
PS > $excel = New-Object -ComObject Excel.Application ==>創建一個excel應用的COM對象 PS > $excel.Visible ==>默認新建的excel視圖不顯示,即沒有打開 False PS > $excel.Visible = $true ==>看到下面的界面

$workbook = $excel.Workbooks.add() ==>現在添加了一個空的工作簿
現在,需連接特定的電子表格。默認情況下,工作簿添加到 Excel 時,會向其中添加三個電子表格(sheet1,sheet2,sheeet3)。這些電子表格可通過數字進行標識。在以下代碼行中,連接第一個電子表格並將返回的電子表格對象存儲在名為 $sheet 的變量中:
$sheet = $workbook.worksheets.Item(1) ==>表示我使用的是第一個sheet
現在我再運行一次$excel.Visible = $true來查看excel變成什么樣了(建好了工作簿並且選擇了sheet1):
現在,可將數據寫入該電子表格。Excel 電子表格中的信息存儲在單元格中。由於單元格位於電子表格之中,所以可使用 $sheet 變量中存儲的電子表格對象訪問特定的單元格。具體方法是使用指代電子表格中行和列的數字。在 Excel 電子表格中,行是數字而列是字母,這一點有些讓人迷惑。但使用自動化模型時,行和列均為數字。第一個數字是行,第二個數字是列。只需對特定單元格進行賦值即可寫入單元格:
$sheet.cells.item(1,1) = "Test" ==>我在第一個單元格填入“Test”
這時,您再運行$excel.Visible = $true,查看excel變成啥樣了:
嗯,意料之中,Excel 的一個不足是工作簿始終會創建三個電子表格,這有點浪費,因為我現在這個測試只需要第一個sheet。幸運的是,可利用自動化刪除多余的電子表格:使用工作表集合連接第三個電子表格並調用 delete 方法。執行相同的操作刪除第二個電子表格:
$workbook.workSheets.item(3).delete() $workbook.WorkSheets.item(2).delete()
這樣只剩下sheet1了,接下來,重命名剩余的電子表格。這一點非常重要,因為如果決定使用 ActiveX 數據對象 (ADO) 來查詢 Excel 電子表格,將在連接字符串中使用此電子表格名稱。因此,要使代碼易讀且直觀,電子表格應具有邏輯名稱。要重命名電子表格,只需向特定電子表格的 name 屬性賦一個值即可。以下代碼將第一個電子表格重命名為 "Processes":
$workbook.WorkSheets.item(1).Name = "Processes"
$sheet = $workbook.WorkSheets.Item("Processes")
這時我們再查看excel的樣子:
以上測試過程的代碼如下:
$excel = New-Object -ComObject Excel.Application #$excel.Visible = $true $workbook = $excel.Workbooks.add() $sheet = $workbook.worksheets.Item(1) $sheet.cells.item(1,1) = "Test" $workbook.workSheets.item(3).delete() $workbook.WorkSheets.item(2).delete() $workbook.WorkSheets.item(1).Name = "Processes" $excel.Visible = $true
$x=2
$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 }
$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++ }
填寫完 Excel 電子表格后,可以調整列的大小以使單元格與其中所存儲數據的尺寸相同。為此,可通過指定要使用的列坐標來創建一個范圍;但是,也可以只使用電子表格的 usedRange 屬性。創建完范圍對象后,選擇 EntireColumn 屬性並使用 AutoFit 方法調整列的大小。由於該方法始終會返回數據,我將結果傳送給 Out-Null cmdlet。從而避免控制台上布滿了雜亂無用的信息。下面是所用的代碼:
$range = $sheet.usedRange $range.EntireColumn.AutoFit() | out-null
至此,已完成所有任務此時的電子表格具有所有進程的名稱和內存工作集,相當不錯。來看看完成后的成果:
以上結果是我電腦里正在運行的進程。我只選擇了兩個字段顯示。
關於整個腳本的代碼,如下:
$processes=Get-Process $excel = New-Object -ComObject Excel.Application #$excel.Visible = $true $workbook = $excel.Workbooks.add() $sheet = $workbook.worksheets.Item(1) $workbook.Worksheets.item(3).delete() $workbook.Worksheets.item(2).delete() $workbook.Worksheets.item(1).name="Processes" $sheet = $workbook.WorkSheets.Item("Processes") $x = 2 $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] 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 } $sheet.cells.item(1,1) = "Name of Process" $sheet.cells.item(1,2) = "Working Set Size" foreach($process in $processes) { $sheet.cells.item($x, 1) = $process.name $sheet.cells.item($x,2) = $process.workingSet $x++ } #end foreach $range = $sheet.usedRange $range.EntireColumn.AutoFit() | out-null
關於powershell寫入excel的簡單知識先介紹到這,其實,在運行的過程的中您會發現,進程中的每個字段填入excel的過程是非常緩慢的,因為它是一個cell一個cell填入的,而不是一下子拷貝到excel中的,這些將在之后的隨筆中介紹。
備注:這篇隨筆是參考微軟官方的一片博客並加入自己的理解寫的,后續還將會簡單介紹powershell操作excel&CSV的其它應用。
如有錯誤,歡迎指正,謝謝!