4

对上述 Com 操作进行搜索会产生可追溯到 09 年甚至更早的链接。也许它没有改变,但我发现自己遇到了“它正在被另一个进程使用”的错误。- 即使我的桌面上没有打开 Excel 应用程序。我必须重新启动才能恢复。

需要明确的是 - 我正在尝试打开现有文件;立即SaveAs()(非常有效),添加一张纸,Save(); Close()然后,重要的是,重复该循环。实际上,我在执行上述“Open Master;”的循环中创建了几十个新工作表;SaveAs(); 编辑东西;节省; 关;

从我看到的示例中,这不是 PowerShell 的典型工作流程。粘贴在最底部的是我的临时脚本 - 非常粗糙且不完整,但事情正在打开他们需要打开的内容并且添加工作表也可以 - 直到我知道我有正确的方法来干净地关闭东西我不担心迭代.

我发现了几个解决关闭的例子:

来自 http://theolddogscriptingblog.wordpress.com/2012/06/07/get-rid-of-the-excel-com-object-once-and-for-all/

$x = New-Object -com Excel.Application
$x.Visible = $True
Start-Sleep 5
$x.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($x)
Remove-Variable x

并来自 http://social.technet.microsoft.com/Forums/windowsserver/en-US/24e57b61-e792-40c1-8aff-b0a8205f48ab/updated-opened-excel-using-powershell?forum=winserverpowershell

Set-ItemProperty $path -name IsReadOnly -value $false
$Excel.ActiveWorkBook.Save()
$openfile.Close() 
$openfile = $null 
$Excel.Quit() 
$Excel = $null 
[GC]::Collect() 

<>

function MakeNewBook($theWeek, $AffID){
    $ExcelFile = "C:\csv\InvoiceTemplate.xlsm"
    $Excel = New-Object -Com Excel.Application
    $Excel.Visible = $True  
    $Workbook = $Excel.Workbooks.Open($ExcelFile)
    $theWeek = $theWeek  -replace "C:\\csv\\", ""
    $theWeek = $theWeek  -replace "\.csv", ""

    $theWeek = "c:\csv\Invoices\" +$AffID +"_" + $theWeek + ".xlsm"

    $SummaryWorksheet = $Workbook.worksheets.Item(1)

    $Workbook.SaveAs($theWeek)
    return $Excel
}

function MakeNewSheet($myBook, $ClassID){
    $SheetName = "w"+$ClassID
    #$Excel = New-Object -Com Excel.Application
    #$Excel.Visible = $True  
    $wSheet = $myBook.WorkSheets.Add()

}

function SaveSheet ($myExcel)
{
    #$WorkBook.EntireColumn.AutoFit()
    #Set-ItemProperty $path -name IsReadOnly -value $false
    $myExcel.ActiveWorkBook.Save()

    $openfile= $myExcel.ActiveWorkBook
    $openfile.Close() 
    $openfile = $null 
    $myExcel.Quit() 
    $myExcel = $null 
    [System.Runtime.Interopservices.Marshal]::ReleaseComObject($myExcel)
    Remove-Variable $myExcel
    [GC]::Collect() 

}

$theWeek = "C:\csv\wkStart2013-11-04.csv"
$x = Import-Csv $theWeek

foreach ($xLine in $x){
    if ($x[0]){
        $AffID = $x[1].idAffiliate
        $myExcel = MakeNewBook $theWeek  $x[1].idAffiliate

        $ClassID = $x[1].idClass
        MakeNewSheet $myExcel $ClassID
        continue
    }
    SaveSheet($myExcel)
    $AffID = $_.$AffID
    $wID = $xLine.idClass
    #MakeNewSheet($wID)
    Echo "$wID"

}
4

4 回答 4

3

作为我自己解决这个问题后的后续行动。我的解决方案是围绕 Ron Thompson 的评论减去函数调用:

# collect excel process ids before and after new excel background process is started
$priorExcelProcesses = Get-Process -name "*Excel*" | % { $_.Id }
$Excel = New-Object -ComObject Excel.Application
$postExcelProcesses = Get-Process -name "*Excel*" | % { $_.Id }

# your code here (probably looping through the Excel document in some way

# try to gently quit
$Excel.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Excel)

# otherwise allow stop-process to clean up
$postExcelProcesses | ? { $priorExcelProcesses -eq $null -or $priorExcelProcesses -notcontains $_ } | % { Stop-Process -Id $_ }
于 2016-03-06T05:39:00.237 回答
2

我的经验是 Quit 方法效果不佳,尤其是在循环时。当您收到错误时,不要重新启动,而是打开任务管理器并查看“进程”选项卡。我敢打赌你会看到 Excel 仍然打开——甚至可能有多个实例。我通过使用 Get-Process 查找 Excel 的所有实例并将它们传送到 Stop-Process 解决了这个问题。似乎这不是必需的,但它对我有用。

于 2013-11-11T14:49:48.063 回答
1

您不必跟踪进程并终止它们。

我的经验是,要正确和完全关闭 Excel(包括循环),您还需要释放 COM 引用。在我自己的测试中发现删除 Excel 的变量还可以确保不存在剩余的引用,这将使 Excel.exe 保持打开状态(就像您在 ISE 中进行调试一样)。

如果不执行上述操作,如果您查看任务管理器,您可能会看到 Excel 仍在运行……在某些情况下,有很多副本。

这与 COM 对象如何包装在“运行时可调用包装器”中有关。

这是应该使用的骨架代码:

$excel = New-Object -ComObject Excel.Application
$excel.Visible = $true
$workbook = $excel.Workbooks.Add()
# or $workbook = $excel.Workbooks.Open($xlsxPath)

# do work with Excel...

$workbook.SaveAs($xlsxPath)
$excel.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)
# no $ needed on variable name in Remove-Variable call
Remove-Variable excel
于 2016-03-12T08:28:00.710 回答
0

尝试这个

$filePath = "E:\TSMBackup\TSMDATAPull\ODCLXTSM01_VM.xlsx"

$excelObj = New-Object -ComObject Excel.Application

$excelObj.Visible = $true

$workBook = $excelObj.Workbooks.Open($filePath)

$workSheet = $workBook.Sheets.Item("Sheet1")

$workSheet.Select()

$workBook.RefreshAll()

$workBook.Save()

$excelObj.Quit()
于 2016-05-06T22:15:56.043 回答