我有大约 20 名异地用户需要每天填写一份 Excel 工作日志。为了帮助他们,我们提供了一个“只读”空白模板,并且我为 powershell 脚本设置了一个桌面图标,以便每天早上为他们准备日志。我的脚本打开只读模板,编辑以填写一些基本信息,然后执行“另存为”操作,以正确的名称将日志存入他们的文档中,并为他们打开文件。
这个脚本多年来一直运行良好,但一周前我们做了改变,将日志文件更改为启用宏(XLSM)的 Excel 工作簿。
为了便于进行这一更改,我打开了旧的 XLSX 并保存了启用宏的工作簿,以确保文件内部格式正确。我还编辑了脚本,将扩展名从 .xlsx 更改为 .xlxm。我在几台用户电脑上远程测试了所有内容。一切正常。
但是在这 20 个用户中,有一个用户遇到了问题,脚本无法保存文件,powershell 错误显示“另存为”时出现文件类型错误。该文件类型存在问题。其他 19 个左右的用户没有遇到此问题。经过一番查找,我发现有人建议使用“add-type”和程序集来指定文件类型。我按照建议添加了以下几行代码。
Add-Type -AssemblyName Microsoft.Office.Interop.Excel
$xlFixedFormat = [Microsoft.Office.Interop.Excel.XlFileFormat]::xlOpenXMLWorkbookMacroEnabled
...
$workbook.saveas($filename,$xlFixedFormat)
这些更改确实修复了该用户计算机上的问题。但它在另一台计算机上引发了新问题。当我运行脚本时,新出现问题的计算机出现以下错误。
PS C:\Users\MyUser\OneDrive\Setup> .\DailyCopy1.ps1
Add-Type : Could not load file or assembly 'Microsoft.Office.Interop.Excel, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c' or one of its dependencies. The system cannot find the file specified.
At C:\Users\MyUser\OneDrive\Setup\DailyCopy1.ps1:2 char:1
+ Add-Type -AssemblyName Microsoft.Office.Interop.Excel
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Add-Type], FileNotFoundException
+ FullyQualifiedErrorId : System.IO.FileNotFoundException,Microsoft.PowerShell.Commands.AddTypeCommand
Unable to get the SaveAs property of the Workbook class
At C:\Users\MyUser\OneDrive\Setup\DailyCopy1.ps1:45 char:10
+ throw $_.Exception.Message
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (Unable to get t... Workbook class:String) [], RuntimeException
+ FullyQualifiedErrorId : Unable to get the SaveAs property of the Workbook class
PS C:\Users\MyUser\OneDrive\Setup>
为了解决第一个错误,我尝试使用另一个 Add-Type 命令并直接指定 DLL 的路径。我还验证了此 dll 确实存在于 PC 上的此路径中。
Add-Type -Path $env:WINDIR\assembly\GAC_MSIL\Microsoft.Office.Interop.Excel\15.0.0.0__71e9bce111e9429c\Microsoft.Office.Interop.Excel.dll
当我在有问题的计算机上启动脚本时,第二个命令成功运行,但脚本后面的“另存为”仍然失败。
有趣的是,它也能正常工作。当我检查用户文档文件夹时,文件以正确的名称创建,并且编辑已到位。但脚本不会继续,并且文件永远不会为用户启动。此外,编辑的 excel 进程仍保留在系统内存中。
你知道为什么这在某些计算机上无法正常工作吗?
有关计算机的一些信息。所有用户都使用相同的 Windows 和 Office 软件。
操作系统 = Win 10 64 位,带最新更新。Office
= Microsoft® Excel® for Microsoft 365 MSO(版本 2311 内部版本 16.0.17029.20108)32 位
我尝试过的方法 = sfc /scannow;在线修复办公室。;.NET Framework 修复工具;多次重启…;在其他计算机上测试,它可以在其他计算机上运行。
以下是目前的完整脚本,包含上述编辑 =
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName Microsoft.Office.Interop.Excel
Add-Type -Path $env:WINDIR\assembly\GAC_MSIL\Microsoft.Office.Interop.Excel\15.0.0.0__71e9bce111e9429c\Microsoft.Office.Interop.Excel.dll
$xlFixedFormat = [Microsoft.Office.Interop.Excel.XlFileFormat]::xlOpenXMLWorkbookMacroEnabled
$EMSDate = Get-Date -Format "yyyy-MM-dd"
$filecheck = "$env:UserProfile\OneDrive\Vessel Templates\EMSV5.xlsm"
# Check if template is XLSM or not
if (!(Test-Path $filecheck)) {
$filename = "$env:UserProfile\OneDrive\WorkingFolder\" + $EMSDate + " Daily Forms.xlsx"
$template = "$env:UserProfile\OneDrive\Vessel Templates\EMSV5.xlsx"
}
else {
$filename = "$env:UserProfile\OneDrive\WorkingFolder\" + $EMSDate + " Daily Forms.xlsm"
$template = "$env:UserProfile\OneDrive\Vessel Templates\EMSV5.xlsm"
}
$EMSEmpList = "$env:UserProfile\OneDrive\Vessel Templates\Data\EMSEmpList.csv"
$EMSStrapping = "$env:UserProfile\OneDrive\Vessel Templates\Data\StrappingTables.csv"
$EMSBoatName = $env:emslocaluser
# If the file does not exist, create it.
if (-not(Test-Path -Path $filename -PathType Leaf)) {
try {
$excel = new-object -comobject Excel.Application
$excel.DisplayAlerts = $false
$excel.ScreenUpdating = $false
$excel.Visible = $false
$excel.UserControl = $false
$excel.Interactive = $false
$workbook = $excel.workbooks.add($template)
$s1 = $workbook.sheets | Where-Object {$_.name -eq 'TABLES'}
$s1.range("A2:A2").cells = $EMSDate
$s1.range("A3:A3").cells = $EMSBoatName
$s1.range("A5:A5").cells = $EMSEmpList
$s1.range("A6:A6").cells = $EMSStrapping
$workbook.saveas($filename,$xlFixedFormat)
$excel.quit()
Start-Sleep -Seconds 1
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)
Start-Sleep -Seconds 2
Remove-Variable excel
Start-Sleep -Seconds 2
Invoke-Item $filename
}
catch {
throw $_.Exception.Message
}
}
# If the file already exists, show the message and do nothing.
else {
$ButtonType = [System.Windows.Forms.MessageBoxButtons]::OK
$MessageIcon = [System.Windows.Forms.MessageBoxIcon]::Error
$MessageBody = "Cannot create new Daily Log because one already exists in the working folder with todays date."
$MessageTitle = "Duplicate"
[System.Windows.Forms.MessageBox]::Show($MessageBody,$MessageTitle,$ButtonType,$MessageIcon)
}