public/Find-ExcelWorkbookText.ps1
function Find-ExcelWorkbookText { <# .SYNOPSIS Find text string pattern within XLSX files in a given location .DESCRIPTION Search all XLSX workbook files for matching text string and return information about the workbook, worksheet, matching value, and location .PARAMETER Path Path (folder) where .XLSX files reside .PARAMETER SearchPattern Text string to search for .PARAMETER SaveFile Save output to CSV file .PARAMETER OutputFile CSV output path+filename .PARAMETER NoRecurse Scan xlsx files in Path location only, do not scan into subfolders .EXAMPLE .\Find-ExcelWorkbookText.ps1 -Path "\\server123\docs" -SearchPattern "Server543" -SaveFile Searches for instances of "Server543" within any cells on any sheets of workbooks in the path \\server123\docs, and save to CSV file. .EXAMPLE Find-ExcelWorkbookText -Path "\\server123\docs" -SearchPattern "Server543" -SaveFile -NoRecurse Searches for instances of "Server543" within any cells on any sheets of workbooks in the path \\server123\docs, but no subfolders, and save to CSV file. .EXAMPLE $results = Find-ExcelWorkbookText -Path "\\server123\docs" -SearchPattern "Server543" $results | Group-Object Workbook | Select-Object Count,Name Returns counts of matching instances by workbook filename .LINK https://github.com/Skatterbrainz/helium/blob/master/docs/Find-ExcelWorkbookText.md #> [CmdletBinding()] param ( [parameter(Mandatory=$False)][string]$Path = "", [parameter(Mandatory=$False)][string]$SearchPattern = "", [parameter(Mandatory=$False)][switch]$SaveFile, [parameter(Mandatory=$False)][switch]$NoRecurse, [parameter(Mandatory=$False)][string]$OutputFile = "$($env:HOME)\Documents\excel_search_$(Get-Date -f 'yyyyMMddhhmm').csv" ) if ([string]::IsNullOrEmpty($Path) -or [string]::IsNullOrEmpty($SearchPattern)) { Write-Warning "Path and SearchPattern inputs cannot be empty" break } if (!(Test-Path $Path)) { Write-Warning "Path not found: $Path" break } function release-comobject($ref) { while ([System.Runtime.InteropServices.Marshal]::ReleaseComObject($ref) -gt 0) {} [void][System.GC]::Collect() } try { $results = @() Write-Verbose "opening microsoft excel session" try { $Excel = New-Object -ComObject Excel.Application } catch { throw "Microsoft Excel does not appear to be installed." } Write-Verbose "requesting files from $Path" if ($NoRecurse) { [array]$files = Get-ChildItem -Path $Path -Filter *.xlsx -ErrorAction Stop } else { [array]$files = Get-ChildItem -Path $Path -Filter *.xlsx -Recurse -ErrorAction Stop } Write-Verbose "$($files.Count) workbook files were found in folder" foreach ($file in $files) { Write-Verbose "workbook: $($file.FullName)" $Workbook = $Excel.Workbooks.Open($file.FullName,$null,$True) Write-Verbose "`t$($Workbook.Sheets.Count) worksheets found in workbook" foreach ($Worksheet in @($Workbook.Sheets)) { Write-Verbose "`tworksheet: $($Worksheet.Name)" $Found = $WorkSheet.Cells.Find($SearchPattern) if ($Found) { Write-Verbose "`tmatches = FOUND" $BeginAddress = $Found.Address(0,0,1,1) $match = [pscustomobject]@{ Workbook = $file.FullName WorkSheet = $Worksheet.Name Column = $Found.Column Row = $Found.Row Text = $Found.Text Address = $BeginAddress } $results += $match $match do { $Found = $WorkSheet.Cells.FindNext($Found) $Address = $Found.Address(0,0,1,1) if ($Address -eq $BeginAddress) { break } Write-Verbose "`tmatches = FOUND" $match = [pscustomobject]@{ Workbook = $file.FullName WorkSheet = $Worksheet.Name Column = $Found.Column Row = $Found.Row Text = $Found.Text Address = $Address } $results += $match $match } until ($False) } else { Write-Verbose "`tmatches = none" } } # foreach worksheet Write-Verbose "closing workbook file" $workbook.close($false) } # foreach file Write-Verbose "finished processing $($files.count) workbook files" } catch { $_.Exception } finally { Write-Verbose "cleaning up session" release-comobject $worksheet release-comobject $workbook release-comobject $excel [gc]::Collect() [gc]::WaitForPendingFinalizers() Remove-Variable excel -ErrorAction SilentlyContinue Get-Process 'excel' | Stop-Process -Force if ($SaveFile) { $results | Export-Csv -Path $OutputFile -NoTypeInformation -Force } else { $results } } } |