应用程序:Microsoft Excel无法访问文件';[<;filename>;]';有几个可能的原因:

应用程序:Microsoft Excel无法访问文件';[<;filename>;]';有几个可能的原因:,excel,powershell,scripting,windows-scripting,excel.application,Excel,Powershell,Scripting,Windows Scripting,Excel.application,我有一个PowerShell脚本,它可以帮助我对多台服务器运行多个查询,并将每个输出保存在不同的CSV中,然后将它们合并到Excel文件中 $Servers = get-content -Path "Servers.txt" $DatabaseName ="master"

我有一个PowerShell脚本,它可以帮助我对多台服务器运行多个查询,并将每个输出保存在不同的CSV中,然后将它们合并到Excel文件中

$Servers = get-content -Path "Servers.txt"                                                                  
$DatabaseName ="master"                                                                                                                             
#$credential = Get-Credential #Prompt for user credentials 
$secpasswd = ConvertTo-SecureString "MyPassword" -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ("sa", $secpasswd)
$QueriesFolder = "Queries\"                                                                                                                         
$ResultFolder = "Results\"                                                                                                                          

ForEach($Server in $Servers)                                                                                                                        
    {
    $DateTime = (Get-Date).tostring("yyyy-MM-dd")                                                                                                   
    ForEach ($filename in get-childitem -path $QueriesFolder -filter "*.sql" | sort-object {if (($i = $_.BaseName -as [int])) {$i} else {$_}} )     
        {
        $oresults = invoke-sqlcmd -ServerInstance $Server -Database $DatabaseName -Credential $credential -InputFile $filename.fullname             
        write-host "Executing $filename on $Server"                                                                                                 
        $BaseNameOnly = Get-Item $filename.fullname | Select-Object -ExpandProperty BaseName
        $oresults | export-csv $ResultFolder$BaseNameOnly.csv -NoTypeInformation -Force
        } 

    $All_CSVs = get-childitem -path $ResultFolder -filter "*.csv" | sort-object {if (($i = $_.BaseName -as [int])) {$i} else {$_}} 
    $Count_CSVs = $All_CSVs.Count
    Write-Host "Detected the following CSV files: ($Count_CSVs)"
    Write-Host " "$All_CSVs.Name"`n"
    $ExcelApp = New-Object -ComObject Excel.Application
    $ExcelApp.SheetsInNewWorkbook = $All_CSVs.Count
    $output = "C:\Users\FrancescoM\Desktop\CSV\Results\" + $Server + " $DateTime.xlsx"
    if (Test-Path $output) 
        {
        Remove-Item $output
        Write-Host Removing: $output because it exists already
        }
    $xlsx = $ExcelApp.Workbooks.Add()
    for($i=1;$i -le $Count_CSVs;$i++) 
        {
        $worksheet = $xlsx.Worksheets.Item($i)
        $worksheet.Name = $All_CSVs[$i-1].Name
        $file = (Import-Csv $All_CSVs[$i-1].FullName)
        $file | ConvertTo-Csv -Delimiter "`t" -NoTypeInformation | Clip
        $worksheet.Cells.Item(1).PasteSpecial()|out-null
        }

    $xlsx.SaveAs($output)
    Write-Host Creating: $output 
    $ExcelApp.Quit() 
    [System.Runtime.Interopservices.Marshal]::ReleaseComObject($xlsx) | Out-Null; 
    Write-Host "Closing all worksheet"
    [System.Runtime.Interopservices.Marshal]::ReleaseComObject($ExcelApp) | Out-Null; 
    Write-Host "Closing Excel"
    [System.GC]::Collect(); 
    [System.GC]::WaitForPendingFinalizers()
    Remove-Item "$ResultFolder\*" -Include *.csv
    Write-Host "Cleaning all *.csv"
    Start-Sleep -Seconds 3
    }

为了使这个脚本更具可移植性,我希望它中提到的所有路径都存储到一个变量中,然后连接起来。 但一旦我改变:

$output = "C:\Users\FrancescoM\Desktop\CSV\Results\" + $Server + " $DateTime.xlsx" 
进入:

$output = $ResultFolder + $Server + " $DateTime.xlsx"
事情变得糟糕,我收到了错误:

Microsoft Excel cannot access the file 'C:\Users\FrancescoM\Documents\Results\0DC80000'.
There are several possible reasons:
• The file name or path does not exist.
• The file is being used by another program.
• The workbook you are trying to save has the same name as a currently open workbook.
At C:\Users\FrancescoM\Desktop\CSV\QueryLauncher.ps1:50 char:2
+     $xlsx.SaveAs($output)
+     ~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (:) [], COMException
    + FullyQualifiedErrorId : System.Runtime.InteropServices.COMException

我不明白,我想我把事情连在一起是对的

我也遵循了这一点,在添加“C:\Windows\SysWOW64\config\systemprofile\desktop”后重新启动了我的计算机,但问题没有得到解决


变量路径怎么会把Excel搞得一团糟

由于您没有在
$ResultFolder
变量中定义完整路径,因此将使用当前工作目录展开它

只要看看你想要的路径:

"C:\Users\FrancescoM\Desktop\CSV\Results\" + $Server + " $DateTime.xlsx"
以及使用部分$ResultFolder变量生成的路径:

C:\Users\FrancescoM\Documents\Results\0DC80000
由于要将输出文件保存在桌面上的文件夹中,请将
$output
设置为

$output = Join-Path $([Environment]::GetFolderPath("Desktop")) "CSV\Results\$Server $DateTime.xlsx"

编辑

从您上次的评论中,我了解到您希望输出位于名为“Results”的子文件夹中,该子文件夹位于脚本本身所在的文件夹中。 在这种情况下,请执行以下操作:

# get the folder this script is running from
$ScriptFolder = if ($PSScriptRoot) { $PSScriptRoot } else { Split-Path $MyInvocation.MyCommand.Path }
# the following paths are relative to the path this script is in
$QueriesFolder = Join-Path -Path $ScriptFolder -ChildPath 'Queries'
$ResultFolder  = Join-Path -Path $ScriptFolder -ChildPath 'Results'
# make sure the 'Results' folder exists; create if not
if (!(Test-Path -Path $ResultFolder -PathType Container)) {
    New-Item -Path $ResultFolder -ItemType Directory | Out-Null
}
然后,当需要保存xlsx文件时,使用以下命令创建完整路径和文件名:

$output = Join-Path -Path $ResultFolder -ChildPath "$Server $DateTime.xlsx"
$xlsx.SaveAs($output)
另外,我建议您使用
Join-Path
cmdlet组合文件路径,或使用
[System.IO.Path]::combine()
而不是像这一行那样将路径连接在一起:
$oresults | export csv$ResultFolder$BaseNameOnly.csv
。如果您忘记在第一个路径部分后加反斜杠,使用后一种方法可能会导致无法预见的路径名


p.S.2 Excel在工具->选项->常规->默认文件位置中设置了自己的默认输出路径,并且不知道脚本的相对路径。这就是为什么您应该使用完整路径和文件名进行保存。

因为您没有在
$ResultFolder
变量中定义完整路径,它将使用当前工作目录展开

只要看看你想要的路径:

"C:\Users\FrancescoM\Desktop\CSV\Results\" + $Server + " $DateTime.xlsx"
以及使用部分$ResultFolder变量生成的路径:

C:\Users\FrancescoM\Documents\Results\0DC80000
由于要将输出文件保存在桌面上的文件夹中,请将
$output
设置为

$output = Join-Path $([Environment]::GetFolderPath("Desktop")) "CSV\Results\$Server $DateTime.xlsx"

编辑

从您上次的评论中,我了解到您希望输出位于名为“Results”的子文件夹中,该子文件夹位于脚本本身所在的文件夹中。 在这种情况下,请执行以下操作:

# get the folder this script is running from
$ScriptFolder = if ($PSScriptRoot) { $PSScriptRoot } else { Split-Path $MyInvocation.MyCommand.Path }
# the following paths are relative to the path this script is in
$QueriesFolder = Join-Path -Path $ScriptFolder -ChildPath 'Queries'
$ResultFolder  = Join-Path -Path $ScriptFolder -ChildPath 'Results'
# make sure the 'Results' folder exists; create if not
if (!(Test-Path -Path $ResultFolder -PathType Container)) {
    New-Item -Path $ResultFolder -ItemType Directory | Out-Null
}
然后,当需要保存xlsx文件时,使用以下命令创建完整路径和文件名:

$output = Join-Path -Path $ResultFolder -ChildPath "$Server $DateTime.xlsx"
$xlsx.SaveAs($output)
另外,我建议您使用
Join-Path
cmdlet组合文件路径,或使用
[System.IO.Path]::combine()
而不是像这一行那样将路径连接在一起:
$oresults | export csv$ResultFolder$BaseNameOnly.csv
。如果您忘记在第一个路径部分后加反斜杠,使用后一种方法可能会导致无法预见的路径名


p.S.2 Excel在工具->选项->常规->默认文件位置中设置了自己的默认输出路径,并且不知道脚本的相对路径。这就是为什么您应该使用完整路径和文件名进行保存。

谢谢@Theo,但我需要一些更便于携带的东西,因为CSV文件夹有时会放在这里,有时会放在那里。我需要指向与可执行文件
目录相同的
“Results\”
文件夹的东西。ps1
@FrancescoMantovani我已将输出文件夹的答案编辑为该脚本运行路径的子文件夹。我想这同样适用于
$QueriesFolder
。你是个专业人士!我还修复了导出csv$ResultFolder$BaseNameOnly.csv。你今天教我一些东西!StackOverflow长寿,谢谢你谢谢你@Theo但我需要一些更便携的东西,因为CSV文件夹有时会放在这里,有时会放在那里。我需要指向与可执行文件
目录相同的
“Results\”
文件夹的东西。ps1
@FrancescoMantovani我已将输出文件夹的答案编辑为该脚本运行路径的子文件夹。我想这同样适用于
$QueriesFolder
。你是个专业人士!我还修复了导出csv$ResultFolder$BaseNameOnly.csv。你今天教我一些东西!祝你长寿,谢谢你