Powershell 脚本用于编辑并“另存为”excel XLSM 文件

Powershell 脚本用于编辑并“另存为”excel XLSM 文件

我有大约 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)
 }

相关内容