从 PowerShell 格式化 Excel 时出现问题

问题描述 投票:0回答:1

长话短说...我有一个脚本,它使用 RESTful API 从设备中提取配置信息。这个脚本比较长,但是长度无关紧要。

我遇到的问题是,当我设计脚本时,我是在 PS 5.1 中编写的,在 PS5.1 中一切正常。现在,尝试在 PS7 中使用脚本时遇到格式化输出的问题。

我目前使用 COM 对象导出到 Excel,而不是流行的 Import-Excel 模块。我希望它是独立的,并注意需要任何额外的东西。另外,我在编写脚本时并不知道该模块的存在,并且我不想重新设计整个脚本。

初始化 Excel 工作簿后,我会移动活动单元格并根据需要插入数据。所有这些都工作正常。当尝试添加单元格边框时,问题就出现了。

如果您在 PS5.1 中进行测试,您会发现它工作得很好,而在 7 中您会收到有关边框粗细的错误。

除了告诉我重新设计脚本并使用 Import-Excel 之外,任何帮助都将不胜感激。

在此输入

这是要演示的一批快速命令示例。显然,这需要在您的系统上安装 Excel。

$Excel = new-object -comobject excel.application
$Excel.Visible = $true
$ExcelWorkBook = $Excel.Workbooks.Add()
$WorkSheetIndex = 1
$ExcelWorkSheet = $ExcelWorkBook.Worksheets.Item($WorkSheetIndex)

$ExcelWorkSheet.Cells.Item(1, 1) = "Test Data"

#Formatting shortcuts
$lineStyle = "microsoft.office.interop.excel.xlLineStyle" -as [type]
$borderWeight = "microsoft.office.interop.excel.xlBorderWeight" -as [type]

$objRange = $ExcelWorkSheet.UsedRange
$objRange.Borders.LineStyle = $lineStyle::xlNone
$objRange.Borders.weight = $borderWeight::xlThin
$ExcelWorkSheet.Cells.Item(1, 1).Font.Size = 16
$ExcelWorkSheet.Cells.Item(1, 1).Font.Bold = $True
[void] $objRange.EntireColumn.Autofit()

PowerShell 7 错误:

OperationStopped: C:\Work\Internal\GIT\Appliance_Administration\Excel_Test.ps1:15
Line |
  15 |  $objRange.Borders.weight = $borderWeight::xlThin
     |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | Unable to set the Weight property of the Borders class

excel powershell formatting com
1个回答
1
投票

GAC 的困境

扩展评论,核心问题是表达式

"microsoft.office.interop.excel.xlBorderWeight" -as [type]
在 PowerShell Core 中计算为
$null

结果,

$borderWeight
$null
,这行:

$objRange.Borders.weight = $borderWeight::xlThin

相当于

$objRange.Borders.weight = $null

相比之下,在 Windows PowerShell 中,表达式

"microsoft.office.interop.excel.xlBorderWeight" -as [type]
返回对
xlBorderWeight
类型的引用:

PS> $borderWeight = "microsoft.office.interop.excel.xlBorderWeight" -as [type]
PS> $borderweight

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     XlBorderWeight                           System.Enum

这是因为 Windows PowerShell 会在 GAC 中搜索程序集,但 PowerShell Core 不会 - 请参阅Windows PowerShell 5.1 和 PowerShell 7.x 之间的差异

在尝试从 GAC 加载之前从模块基本路径加载程序集

以前,当二进制模块在 GAC 中具有模块程序集时,我们会先从 GAC 加载该程序集,然后再尝试从模块基本路径加载它。

解决方法

一个快速而肮脏的解决方法是使用枚举的常量值 - 例如

$XlBorderWeight_xlThin = 2;
...
$objRange.Borders.weight = $XlBorderWeight_xlThin

但请注意,您也遇到了同样的问题

$lineStyle = "microsoft.office.interop.excel.xlLineStyle" -as [type]

看起来

$objRange.Borders.LineStyle = $null
不会导致错误,而
$objRange.Borders.weight = $null
会导致错误。

添加类型

或者,您可以自己在 PowerShell Core 中手动从 GAC 加载程序集:

Add-Type -Path "C:\WINDOWS\assembly\GAC_MSIL\Microsoft.Office.Interop.Excel\15.0.0.0__71e9bce111e9429c\Microsoft.Office.Interop.Excel.dll"
如果您想找到此路径的神奇值,您可以使用 Windows PowerShell 5.1:

PS> ("microsoft.office.interop.excel.xlLineStyle" -as [type]).Assembly.Location C:\WINDOWS\assembly\GAC_MSIL\Microsoft.Office.Interop.Excel\15.0.0.0__71e9bce111e9429c\Microsoft.Office.Interop.Excel.dll
您需要使用 PowerShell Core 中的硬编码路径。

选角

但这并不是故事的全部,因为一旦加载类型,您仍然会得到相同的错误,但原因不同。

$objRange.Borders.weight

 是一个 
Variant
 值 - 请参阅:

PS> $objRange.Borders | gm TypeName: System.__ComObject#{00020854-0000-0000-c000-000000000046} Name MemberType Definition ---- ---------- ---------- ... snip ... Weight Property Variant Weight () {get} {set}
Windows PowerShell 似乎很乐意将 

xlBorderWeight

 枚举值转换为 
Variant
,但 PowerSHell Core 
,因此您必须执行类似的操作,而不是通过将枚举强制转换为int

$objRange.Borders.weight = [int]$borderWeight::xlThin
完成所有这些后,您的代码应该最终可以工作......

© www.soinside.com 2019 - 2024. All rights reserved.