I have a couple questions about a script I am working on (see below). In short, the script updates connections in all Excel files in a given directory, with a couple exceptions.
First, it seems that when Powershell executes a command to open, refresh, save, etc a workbook, it doesn’t necessarily wait for that task to complete before moving on to the next task. I have some Start-Sleep commands inserted to add delays, but it doesn’t seem to work across the board, as some files are still throwing some errors. At the least, Start-Sleep needs to be set to a high delay to accommodate the larger files, which adds a lot of unnecessary delay to the smaller files, subsequently causing the script to take a lot longer to run. For the refresh task, I added “While ($ExcelWorkbook.ODBCConnection.Refreshing) {Start-Sleep -Seconds 1}”, which might work for other tasks, but I’m not sure what the syntax would need to be for other tasks, such as opening, saving, etc.
Secondly, I occasionally see some errors like the following, but I’m not entirely sure why. They don’t always show up every time I run the script, and are not always on the same files. I’m guessing some of them might be due to Powershell performing a task before Excel has finished the previous task, but I’m not sure, as I am less familiar with working with Excel in Powershell. If it makes any difference, they seem to start showing up after the script has gone through a few dozen files successfully, so maybe something is being left open from each file and taxing the system?
Thanks in advance for the help,
Andrew
Method invocation failed because [System.__ComObject] does not contain a method named 'Save'.
At C:\Users\administrator.NHFM\Desktop\Refresh-ExcelConnections.ps1:44 char:9
+ $ExcelWorkbook.Save()
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (Save:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
You cannot call a method on a null-valued expression.
At C:\Users\administrator.NHFM\Desktop\Refresh-ExcelConnections.ps1:59 char:9
+ $Excel.Workbooks.Close()
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Call was rejected by callee. (Exception from HRESULT: 0x80010001 (RPC_E_CALL_REJECTED))
At C:\Users\administrator.NHFM\Desktop\Refresh-ExcelConnections.ps1:44 char:9
+ $ExcelWorkbook.Save()
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
Exception calling "Quit" with "0" argument(s): "Call was rejected by callee. (Exception from HRESULT: 0x80010001
(RPC_E_CALL_REJECTED))"
At C:\Users\administrator.NHFM\Desktop\Refresh-ExcelConnections.ps1:63 char:5
+ $Excel.Quit()
+ ~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : COMException
# Set library path variable
$LibraryPath = “\\server\path”
# Open Excel
$Excel = New-Object -ComObject Excel.Application
Start-Sleep -Seconds 5
# Set visibility of Excel and alerts
$Excel.Visible = $False
$Excel.DisplayAlerts = $False
# Get Excel files
$AllExcelFiles = Get-ChildItem $LibraryPath | Where {($_.Name -like "*.xls*") -and ($_.Name -notlike "TEST*")}
# Settings for PDF Export
$ExportPDFList = Join-Path -Path $LibraryPath -ChildPath "PDF Exports\~ExportPDFList.txt"
$xlFixedFormat = "Microsoft.Office.Interop.Excel.xlFixedFormatType" -as [type]
# Refresh each Excel file in $LibraryPath
foreach ($File in $AllExcelFiles)
{
Write-Host $File.Name -ForegroundColor Green
$WorkbookPath = $File.Fullname
# Open the workbook
$Timestamp = Get-Date -DisplayHint Time
Write-Host " "$($Timestamp) "- Opening..."
$ExcelWorkbook = $Excel.Workbooks.Open($WorkbookPath)
Start-Sleep -Seconds 10
# Refresh All the pivot tables data
$Timestamp = Get-Date -DisplayHint Time
Write-Host " "$Timestamp "- Refreshing..."
$ExcelWorkbook.RefreshAll()
While ($ExcelWorkbook.ODBCConnection.Refreshing) {Start-Sleep -Seconds 1}
# Save the file
$Timestamp = Get-Date -DisplayHint Time
Write-Host " "$Timestamp "- Saving..."
$ExcelWorkbook.Save()
# Export PDF
$Export = Select-String -Path $ExportPDFList -Pattern $File.Name
if ($Export -ne $null)
{
$Timestamp = Get-Date -DisplayHint Time
Write-Host " "$Timestamp "- Exporting PDF..."
$PDFPath = Join-Path -Path $LibraryPath -ChildPath ("PDF Exports\$($File.BaseName)" + ".pdf")
$ExcelWorkbook.ExportAsFixedFormat($xlFixedFormat::xlTypePDF, $PDFPath)
}
# Close file
$Timestamp = Get-Date -DisplayHint Time
Write-Host " "$Timestamp "- Closing..."
$Excel.Workbooks.Close()
}
# Close Excel
$Excel.Quit()
Get-Process -Name "*Excel*" | Stop-Process
#Release Excel object from memory
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Excel)