脚本专栏 
首页 > 脚本专栏 > 浏览文章

PowerShell操作Excel、CSV详细介绍

(编辑:jimmy 日期: 2024/11/26 浏览:3 次 )

Powershell针对Excel的一些简单操作

  稍微高级点的语言都会涉及到对COM对象的操作,作为微软自己进化的脚本语言,powershell有这个功能一点不稀奇,首先它使用 .NET Framework 提供的强大类库,很多特性和C#相似;其次,虽然作为脚本但它面向对象。使用powershell来管理WMI和COM更简单。

  用微软官方的话概括powershell就是:

  Windows PowerShell"//img.jbzj.com/file_images/article/201501/201511114415297.jpg" alt="" />

Get-Process cmdlet显示当前本地进程运行状态,包括处于打开状态的句柄数量、各种内存占用视图以及 CPU 使用率的快照。powershell和Linux shell一个很大的不同点就是大小写不敏感,无论是系统函数还是命令。这点可以减少犯错的概率。

  您可能疑惑为什么讲这个?对于系统管理员来说,冗长的数据背后隐藏着大量细节,get-process是获取本地进程运行情况,当然加上-computername参数后可以访问远程计算机,但目前这个对于网络管理员来说犹如海市蜃楼,所以不得不使用windows WMI和 Win32_Process WMI 类来监视远程系统并以实用方式显示信息。如果认为 Get-Process 的输出内容非常丰富,请再仔细看看 Win32_Process 的输出:

PowerShell操作Excel、CSV详细介绍

 很明显,这个输出很详细,但是可读性不强,管理员需要的是易于阅读的内存占用量报告。可以转用Excel实现自动操作。

 自动化 Excel 有多难?实际上非常简单,因为 Microsoft 已创建了专门用于处理 Excel 的自动化模型。程序 ID 是 Excel.Application,它是一个 COM 对象。创建 Excel.Application 对象的实例时,Excel 会默认启动并运行,只是您看不见它。但是,可使用 visible 属性让 Excel 显示出来。

以下代码显示了如何创建 Excel.Application 对象、查询 visible 属性的状态,然后将 visible 属性设为 true:
复制代码 代码如下:
PS > $excel = New-Object -ComObject Excel.Application   ==>创建一个excel应用的COM对象
PS > $excel.Visible    ==>默认新建的excel视图不显示,即没有打开
False
PS > $excel.Visible = $true    ==>看到下面的界面

  然后,您会看到一个非常奇怪的 Excel 视图,它看起来就像 Excel 应用程序的一个外壳(如下图)。没有工作簿、没有电子表格,—个是光秃秃的 Excel。

PowerShell操作Excel、CSV详细介绍

当然,这个肯定是无法使用的,但是它是建立工作簿的前提,它是存放工作簿的容器。现在我们需要将一个工作簿添加到应用程序中。为此,需要借助工作簿对象的 add 方法。工作簿对象是从主 Excel.Application 对象进行访问的,正如您看到的,我们将工作簿对象存储在一个名为 $workbook 的变量中:
复制代码 代码如下:
$workbook = $excel.Workbooks.add()   ==>现在添加了一个空的工作簿

现在,需连接特定的电子表格。默认情况下,工作簿添加到 Excel 时,会向其中添加三个电子表格(sheet1,sheet2,sheeet3)。这些电子表格可通过数字进行标识。在以下代码行中,连接第一个电子表格并将返回的电子表格对象存储在名为 $sheet 的变量中:
复制代码 代码如下:
$sheet = $workbook.worksheets.Item(1)   ==>表示我使用的是第一个sheet

现在我再运行一次$excel.Visible = $true来查看excel变成什么样了(建好了工作簿并且选择了sheet1):

PowerShell操作Excel、CSV详细介绍

现在,可将数据写入该电子表格。Excel 电子表格中的信息存储在单元格中。由于单元格位于电子表格之中,所以可使用 $sheet 变量中存储的电子表格对象访问特定的单元格。具体方法是使用指代电子表格中行和列的数字。在 Excel 电子表格中,行是数字而列是字母,这一点有些让人迷惑。但使用自动化模型时,行和列均为数字。第一个数字是行,第二个数字是列。只需对特定单元格进行赋值即可写入单元格:

复制代码 代码如下:
$sheet.cells.item(1,1) = "Test"   ==>我在第一个单元格填入“Test”

这时,您再运行$excel.Visible = $true,查看excel变成啥样了:

PowerShell操作Excel、CSV详细介绍

嗯,意料之中,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"

  现在,需连接重命名后的电子表格。使用工作表对象的 Item 方法并将电子表格的名称指定给它: 
复制代码 代码如下:
$sheet = $workbook.WorkSheets.Item("Processes")

   这时我们再查看excel的样子:

PowerShell操作Excel、CSV详细介绍

以上测试过程的代码如下:

复制代码 代码如下:
$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

下面我们开始将process中的内容移植到excel中。
 
  电子表格的第一行将包含标头信息。将绘制边框并使属性名称显示为粗体。由于数据将从第二行开始,因此将值 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++
}

  填写完 Excel 电子表格后,可以调整列的大小以使单元格与其中所存储数据的尺寸相同。为此,可通过指定要使用的列坐标来创建一个范围;但是,也可以只使用电子表格的 usedRange 属性。创建完范围对象后,选择 EntireColumn 属性并使用 AutoFit 方法调整列的大小。由于该方法始终会返回数据,我将结果传送给 Out-Null cmdlet。从而避免控制台上布满了杂乱无用的信息。下面是所用的代码:
复制代码 代码如下:
$range = $sheet.usedRange
$range.EntireColumn.AutoFit() | out-null

  至此,已完成所有任务此时的电子表格具有所有进程的名称和内存工作集,相当不错。来看看完成后的成果:

PowerShell操作Excel、CSV详细介绍以上结果是我电脑里正在运行的进程。我只选择了两个字段显示。

关于整个脚本的代码,如下:
复制代码 代码如下:
$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的其它应用。

  如有错误,欢迎指正,谢谢!

上一篇:Powershell中显示隐藏文件的方法
下一篇:Python中调用PowerShell、远程执行bat文件实例
一句话新闻
一文看懂荣耀MagicBook Pro 16
荣耀猎人回归!七大亮点看懂不只是轻薄本,更是游戏本的MagicBook Pro 16.
人们对于笔记本电脑有一个固有印象:要么轻薄但性能一般,要么性能强劲但笨重臃肿。然而,今年荣耀新推出的MagicBook Pro 16刷新了人们的认知——发布会上,荣耀宣布猎人游戏本正式回归,称其继承了荣耀 HUNTER 基因,并自信地为其打出“轻薄本,更是游戏本”的口号。
众所周知,寻求轻薄本的用户普遍更看重便携性、外观造型、静谧性和打字办公等用机体验,而寻求游戏本的用户则普遍更看重硬件配置、性能释放等硬核指标。把两个看似难以相干的产品融合到一起,我们不禁对它产生了强烈的好奇:作为代表荣耀猎人游戏本的跨界新物种,它究竟做了哪些平衡以兼顾不同人群的各类需求呢?
友情链接:杰晶网络 DDR爱好者之家 南强小屋 黑松山资源网 白云城资源网 网站地图 SiteMap