创建Excel实例时如何防止出现“文件在另一个应用程序中打开”的消息

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

我之前运行的 PowerShell 脚本运行得很好,但由于某种原因,弹出了一条消息,表示该文件已在另一个应用程序中打开。我检查了任务管理器,Excel 进程未激活。如何阻止此消息?

留言

# create excel instance
$excel = new-object -comobject excel.application

# show excel instance
$excel.Visible = $true

# maximize excel window
$excel.WindowState = "xlMaximized"

# locate file
$filePath = "https://company-my.sharepoint.com/:x:/r/personal/user/Documents/a%20-%201st%20Rotation/name.xlsx?d=wffe0f3f574fd4e40810b1dc67d6dd298&csf=1&web=1&e=JDzZT2"

# open excel workbook
$workbook = $excel.Workbooks.Open($filePath)

# set excel worksheet
$worksheet = $workbook.ActiveSheet

# get yesterdays date
$yesterdaysDate = (Get-Date).AddDays(-1).ToString("M/d/yyyy")

# unfilter excel worksheet
if ($worksheet.AutoFilterMode) {
    $worksheet.AutoFilterMode = $false
}

# filter excel worksheet
$filter = $worksheet.ListObjects("OfficeForms.Table").Range.AutoFilter(3, $yesterdaysDate)

# define microzones
$zone1 = @()
$zone2 = @()
$zone3 = @()
$zone4 = @()
$zone5 = @()
$zone6 = @()
$zone7 = @()
$superZone = @($zone1; $zone2; $zone3; $zone4; $zone5; $zone6; $zone7)

# get excel values
$values = @()
for ($i = 9; $i -le 15; $i++) {
    foreach ($cell in $worksheet.ListObjects("Table1").Range.Columns.Item($i).SpecialCells(12).Cells) {
    $values += $cell.Value2
    }
}

# remove excel values
$values = $values | Where-Object { $_ -match "^\d" }

# identify incomplete microzones
$emptyValues = @()
foreach ($zone in $superZone) {
    if (-not ($values -contains $zone)) {
        $emptyValues += $zone
    }
}

# unfilter excel worksheet
if ($worksheet.AutoFilterMode) {
    $worksheet.AutoFilterMode = $false
}

# close excel workbook
$excel.Workbooks.Close($false)
$object = [System.Runtime.InteropServices.Marshal]::ReleaseComObject($workbook) | Out-Null

# close excel instance
$excel.Quit()
$object = [System.Runtime.InteropServices.Marshal]::ReleaseComObject($excel) | Out-Null

# garbage collection
$garbage = [System.GC]::Collect()
$garbage = [System.GC]::WaitForPendingFinalizers()

# create outlook instance
$outlook = New-Object -ComObject Outlook.Application

# create mail item
$mail = $outlook.CreateItem(0)

# Set mail values
$mail.To = "address"
$mail.Subject = "subject"
$mail.Body = "body"

# send mail values
$mail.Send()

# close outlook instance
$outlook.Quit()

我传递一个 Excel Web URL 作为保存到 OneDrive 的文件路径,因为它会自动保存 MS 表单提交。我尝试关闭工作簿、退出实例、释放 com 对象并收集垃圾。我希望文件关闭,以便在重新运行脚本时可以重新打开,但该消息仍然弹出,并且阻止发送电子邮件。

excel powershell automation
1个回答
0
投票

您遇到的问题可能是由于文件被任务管理器中未显示的进程锁定或保持打开状态,或者可能与 PowerShell 脚本与 Excel COM 对象交互的方式有关。您可以采取以下几个步骤来确保文件未被锁定并正确释放 COM 对象:

  1. 确保正确处置 COM 对象:确保在脚本中正确释放所有 COM 对象,以防止文件上出现任何锁定。

  2. 正确关闭Excel工作簿:关闭工作簿时,请确保工作簿已正确关闭,并且Excel应用程序实例已正确退出。

  3. 检查后台进程:有时,可能有后台进程正在保留文件。使用像 Process Explorer 这样的工具来检查是否有任何可能保留该文件的延迟进程。

这是脚本的更新版本,其中包含一些附加步骤,以确保正确释放 COM 对象:

# create excel instance
$excel = New-Object -ComObject Excel.Application

# show excel instance
$excel.Visible = $true

# maximize excel window
$excel.WindowState = "xlMaximized"

# locate file
$filePath = "https://company-my.sharepoint.com/:x:/r/personal/user/Documents/a%20-%201st%20Rotation/name.xlsx?d=wffe0f3f574fd4e40810b1dc67d6dd298&csf=1&web=1&e=JDzZT2"

# open excel workbook
$workbook = $excel.Workbooks.Open($filePath)

# set excel worksheet
$worksheet = $workbook.ActiveSheet

# get yesterdays date
$yesterdaysDate = (Get-Date).AddDays(-1).ToString("M/d/yyyy")

# unfilter excel worksheet
if ($worksheet.AutoFilterMode) {
    $worksheet.AutoFilterMode = $false
}

# filter excel worksheet
$filter = $worksheet.ListObjects("OfficeForms.Table").Range.AutoFilter(3, $yesterdaysDate)

# define microzones
$zone1 = @()
$zone2 = @()
$zone3 = @()
$zone4 = @()
$zone5 = @()
$zone6 = @()
$zone7 = @()
$superZone = @($zone1; $zone2; $zone3; $zone4; $zone5; $zone6; $zone7)

# get excel values
$values = @()
for ($i = 9; $i -le 15; $i++) {
    foreach ($cell in $worksheet.ListObjects("Table1").Range.Columns.Item($i).SpecialCells(12).Cells) {
    $values += $cell.Value2
    }
}

# remove excel values
$values = $values | Where-Object { $_ -match "^\d" }

# identify incomplete microzones
$emptyValues = @()
foreach ($zone in $superZone) {
    if (-not ($values -contains $zone)) {
        $emptyValues += $zone
    }
}

# unfilter excel worksheet
if ($worksheet.AutoFilterMode) {
    $worksheet.AutoFilterMode = $false
}

# close excel workbook without saving
$workbook.Close($false)
[System.Runtime.InteropServices.Marshal]::ReleaseComObject($workbook) | Out-Null

# close excel instance
$excel.Quit()
[System.Runtime.InteropServices.Marshal]::ReleaseComObject($excel) | Out-Null

# garbage collection
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()

# create outlook instance
$outlook = New-Object -ComObject Outlook.Application

# create mail item
$mail = $outlook.CreateItem(0)

# Set mail values
$mail.To = "address"
$mail.Subject = "subject"
$mail.Body = "body"

# send mail values
$mail.Send()

# close outlook instance
$outlook.Quit()
[System.Runtime.InteropServices.Marshal]::ReleaseComObject($outlook) | Out-Null

# garbage collection
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()

确保:

  • 所有 COM 对象(例如,
    $workbook
    $excel
    $outlook
    )在使用后都会被释放。
  • 调用垃圾回收来清理对象。
  • 除非必要,否则您不会保存工作簿 (
    $workbook.Close($false)
    )。

这应该有助于防止文件被任何残留进程锁定。

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