用于搜索 excel 个文件的目录以查找仅搜索 1 个文件的字符串的 Powershell 脚本

Powershell script to search through a directory of excel files to find a string only searching through 1 file

我在 https://shuaiber.medium.com/ 上找到了这个脚本 我想用它在充满 excel 个文件的文件夹中查找某个字符串。 我遇到的问题是它基本上只搜索 1 个文件然后停止...

这是脚本

Function Search-Excel {
    [cmdletbinding()]
    Param (
        [parameter(Mandatory, ValueFromPipeline)]
        [ValidateScript({
            Try {
                If (Test-Path -Path $_) {$True}
                Else {Throw "$($_) is not a valid path!"}
            }
            Catch {
                Throw $_
            }
        })]
        [string]$Source,
        [parameter(Mandatory)]
        [string]$SearchText
        #You can specify wildcard characters (*, ?)
    )
    $Excel = New-Object -ComObject Excel.Application
    Try {
        $Source = Convert-Path $Source
    }
    Catch {
        Write-Warning "Unable locate full path of $($Source)"
        BREAK
    }
    $Workbook = $Excel.Workbooks.Open($Source)
    ForEach ($Worksheet in @($Workbook.Sheets)) {
       
        $Found = $WorkSheet.Cells.Find($SearchText) #What
        If ($Found) {
            
            $BeginAddress = $Found.Address(0,0,1,1)
            #Initial Found Cell
            [pscustomobject]@{
                WorkSheet = $Worksheet.Name
                Column = $Found.Column
                Row =$Found.Row
                Text = $Found.Text
                Address = $BeginAddress
            }
            Do {
                $Found = $WorkSheet.Cells.FindNext($Found)
                $Address = $Found.Address(0,0,1,1)
                If ($Address -eq $BeginAddress) {
                    BREAK
                }
                [pscustomobject]@{
                    WorkSheet = $Worksheet.Name
                    Column = $Found.Column
                    Row =$Found.Row
                    Text = $Found.Text
                    Address = $Address
                }                 
            } Until ($False)
        }
        Else {
            Write-Warning "[$($WorkSheet.Name)] Nothing Found!"
        }
    }
    $workbook.close($false)
    [void][System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$excel)
    [gc]::Collect()
    [gc]::WaitForPendingFinalizers()
    Remove-Variable excel -ErrorAction SilentlyContinue
}

然后我会用

Get-ChildItem -路径 "C:\excelfiles" -Recurse -Include *.xls, *.xlsx, *.xlsm | Select-对象-属性目录,名称| ForEach-Object { "{0}{1}" -f $.Directory, $.Name } |搜索-Excel -SearchText MyText

我知道它只能搜索 1 个文件,因为我查看了另一个文件并试图让它发回给我确认,但它不起作用。

如有任何帮助,我们将不胜感激。

您将需要在函数中包含一个循环,或者将函数放在 ForEach-Object 循环中。对于功能更改,您可以执行以下操作:

Function Search-Excel {
    [cmdletbinding()]
    Param (
        [parameter(Mandatory, ValueFromPipeline)]
        [ValidateScript({
            Try {
                If (Test-Path -Path $_) {$True}
                Else {Throw "$($_) is not a valid path!"}
            }
            Catch {
                Throw $_
            }
        })]
        [string]$Source,
        [parameter(Mandatory)]
        [string]$SearchText
        #You can specify wildcard characters (*, ?)
    )
    $Excel = New-Object -ComObject Excel.Application
    ForEach($Path in $Source){
###     <the rest of your existing code here, adjusted to work with $Path instead of $Source>
    }
    [void][System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$excel)
    [gc]::Collect()
    [gc]::WaitForPendingFinalizers()
    Remove-Variable excel -ErrorAction SilentlyContinue
}

或者,要使用您现有的函数,您可以这样做:

Get-ChildItem -Path "C:\excelfiles" -Recurse -Include *.xls, *.xlsx, *.xlsm |
    ForEach-Object { Search-Excel -Source $_.FullName -SearchText MyText }

那么让我们用你的命令来谈谈一些事情。

Get-ChildItem -Path "C:\excelfiles" -Recurse -Include *.xls, *.xlsx, *.xlsm | Select-Object -Property Directory, Name | ForEach-Object { "{0}{1}" -f $.Directory, $.Name } | Search-Excel -SearchText MyText

如果我们将其分解成单独的部分(用竖线分隔),我们也许能够找出问题所在。第一部分 Get-ChildItem 仅查找匹配 *.xls*.xlsx*.xlsm 的文件,因此已经排除了目录。那么,这个函数return到底是做什么的呢?如果您要查看对象类型,您会看到 System.IO.FileInfo,它内置了一堆属性。其中之一是所需的完整文件路径,.FullName.

目前,Search-Excel 设置为仅搜索一个文件。如果您想一次搜索多个文件,则需要在某处进行循环。在我看来,最简单的地方就是在函数之外,就像这样:

Get-ChildItem -Path "C:\excelfiles" -Recurse -Include *.xls, *.xlsx, *.xlsm | Foreach-Object { Search-Excel -Source $_.FullName -SearchText MyText }