Excel 使用 PowerShell 搜索多个字符串

问题描述 投票:0回答:1

我有下面的代码根据单个字符串搜索的需要工作 - 现在我试图了解允许用户输入多个字符串的最佳方法,这些字符串会将结果填充到返回电子邮件的数据变量中?对此最好的循环方法是什么:For 循环、ForEach、Do While 或 Do Until?您可以看到我当前设置为搜索单个字符串 MESH (SearchText MESH) 的位置。我应该用 $searchString 替换该单个条目并使用循环方法来填充该变量吗?

我尝试了以下方法 - 但它只产生最后一个值网格。尝试将两个字符串搜索的结果串联到 $data

$strings = @("Alert", "MESH")
foreach ($i in $strings) {
$share = "\\servername\share\folder"
$data=@()
$data = (Get-ChildItem -Path "$share\FIGS\*" -Recurse -Include *.xls, *.xlsx, *.xlsm | Select-Object -Property Directory, Name | ForEach-Object { "{0}\{1}" -f $_.Directory, $_.Name } | Search-Excel -SearchText $i)
}

这是完整的脚本:

# Credits to Boe Prox for his article on https://mcpmag.com/articles/2018/04/06/find-excel-data-with-powershell.aspx
# from which this code is pulled
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)) {
# Find Method https://msdn.microsoft.com/en-us/vba/excel-vba/articles/range-find-method-excel
$Found = $WorkSheet.Cells.Find($SearchText) #What
If ($Found) {
# Address Method https://msdn.microsoft.com/en-us/vba/excel-vba/articles/range-address-property-excel
$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
}
#echo $myObject
} 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
}
$share = "\\servername\share\folder"
$data = (Get-ChildItem -Path "$share\FIGS\*" -Recurse -Include *.xls, *.xlsx, *.xlsm | Select-Object -Property Directory, Name | ForEach-Object { "{0}\{1}" -f $_.Directory, $_.Name } | Search-Excel -SearchText MESH)

$exportObject=@() 
ForEach ($row in $data) {

        $ExciterObject = New-Object PSObject
        $ExciterObject | Add-Member -MemberType NoteProperty -Name "WorkSheet" -Value $row.WorkSheet
        $ExciterObject | Add-Member -MemberType NoteProperty -Name "Column" -Value $row.Column 
        $ExciterObject | Add-Member -MemberType NoteProperty -Name "Row" -Value $row.Row 
        $ExciterObject | Add-Member -MemberType NoteProperty -Name "Text" -Value $row.Text
        $ExciterObject | Add-Member -MemberType NoteProperty -Name "Address" -Value $row.Address
        $exportObject += $ExciterObject

        }
                function ConvertTo-HTMLTable ($obj) {
    # Accepts a System.Data.DataTable object or an array of PSObjects and converts to styled HTML table

    # add type needed to replace HTML special characters into entities
    Add-Type -AssemblyName System.Web

    $sb = New-Object -TypeName System.Text.StringBuilder
    [void]$sb.AppendLine('<table>')
    if ($null -ne $obj) {
        if (([object]$obj).GetType().FullName -eq 'System.Data.DataTable'){
            # it is a DataTable; convert to array of PSObjects
            $obj = $obj | Select-Object * -ExcludeProperty ItemArray, Table, RowError, RowState, HasErrors
        }
        $headers = $obj[0].PSObject.Properties | Select -ExpandProperty Name
        [void]$sb.AppendLine('<thead><tr>')
        foreach ($column in $headers) {
            [void]$sb.AppendLine(('<th>{0}</th>' -f [System.Web.HttpUtility]::HtmlEncode($column)))
        }
        [void]$sb.AppendLine('</tr></thead><tbody>')
        $row = 0
        $obj | ForEach-Object {
            # add inline style for zebra color rows
            if ($row++ -band 1) {
                $tr = '<tr style="background-color: {0};">' -f $oddRowBackColor
            } 
            else {
                $tr = '<tr>'
            }
            [void]$sb.AppendLine($tr)
            foreach ($column in $headers) {
                [string]$val = $($_.$column)
                if ([string]::IsNullOrWhiteSpace($val)) { 
                    $td = '<td>&nbsp;</td>' 
                } 
                else { 
                    $td = '<td>{0}</td>' -f [System.Web.HttpUtility]::HtmlEncode($val)
                }
                [void]$sb.Append($td)
            }
            [void]$sb.AppendLine('</tr>')
        }

        [void]$sb.AppendLine('</tbody>')
    }
    [void]$sb.AppendLine('</table>')

    return $sb.ToString()
}


$headerBackColor = '#4F81BD'  # backgroundcolor for column headers
$oddRowBackColor = '#DCE6F1'  # background color for odd rows

$style = @"
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <title>Report</title>
    <meta name="generator" content="PowerShell" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <style type="text/css">
    body {
        font-family: Verdana, Arial, Geneva, Helvetica, sans-serif;
        font-size: 12px;
        color: black;
    }

    table, td, th {
        border-color: black;
        border-style: solid;
        font-family: Verdana, Arial, Geneva, Helvetica, sans-serif;
        font-size: 11px;
    }
    table {
        border-width: 0 0 1px 1px;
        border-spacing: 0;
        border-collapse: collapse;
    }

    td, th {
        margin: 0;
        padding: 4px;
        border-width: 1px 1px 0 0;
        text-align: left;
    }
    th {
        color: white;
        background-color: $headerBackColor;
        font-weight: bold;
    }
    </style>

<p><span style="color: #0000ff;"><strong>Follow below instructions:</strong></span></p>
<ol>
<li>some text (<span style="color: #3366ff;"><strong>some text</strong></span>) some text.</li>
<li>some text &ldquo;some text&rdquo; some text.</li>
<li>some text &gt; some text.</li>
<li>some text (some text). some text.</li>
<li>some text &ldquo;<span style="color: #3366ff;"><strong>some text</strong></span>&rdquo;.</li>
<li>some text &ldquo;<span style="color: #3366ff;"><strong>1101 some text</strong></span>&rdquo;.</li>
<li>some text.</li>
<li>some text&ndash; some text &ldquo;<span style="color: #3366ff;"><strong>some text</strong></span>&rdquo; &ndash; some text.</li>
<li>some text &gt; some text <span style="color: #3366ff;"><strong>some text</strong></span> some text <span style="color: #3366ff;"><strong>Ping</strong></span>. some text&ldquo;<span style="color: #3366ff;"><strong>Ping successful</strong></span>&rdquo;.</li>
<li>some text.</li>
<li>some text&rdquo;.</li>
</ol>
"@
####SET EMAIL VALUES####
$bodyA = '{0}</head><body>{1}</body></html>' -f $style, (ConvertTo-HTMLTable $exportObject)
$EmailTo = "[email protected]"
$EmailFrom = "[email protected]"
$Subject = "My Test" 
$Body = $bodyA 
$SMTPServer = "mail.domain.org" 

####EMAIL PROCESS ####
$anonUsername = "anonymous"
$anonPassword = ConvertTo-SecureString -String "anonymous" -AsPlainText -Force
$anonCredentials = New-Object System.Management.Automation.PSCredential($anonUsername,$anonPassword)
Send-MailMessage -smtpserver "$SMTPServer" -from "$EmailFrom" -to "$EmailTo" -subject "$Subject" -bodyAsHtml "$Body" -credential $anonCredentials

powershell
1个回答
0
投票

我已经更改了原始函数以接受搜索字符串(或值)数组并循环它们。
另外,我向该函数添加了更多参数,以便您可以指定必须在何处进行搜索 (LookIn)、字符串搜索是否应匹配整个单词或仅匹配其一部分 (LookAt),以及用于指定是否匹配的开关。搜索应区分大小写。

function Search-Excel {
    # original code https://mcpmag.com/articles/2018/04/06/find-excel-data-with-powershell.aspx
    [cmdletbinding()]
    Param (
        [parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0)]
        [ValidateScript({
            if (!(Test-Path -Path $_ -PathType Leaf)) {Throw "File does not exist"}
            $true
        })]
        [Alias('FullName')]
        [string]$Path,

        # Can be a string or any Microsoft Excel data type or an array of search items.
        # You can specify wildcard characters (*, ?) if this is a string
        [parameter(Mandatory = $true, Position = 1)]
        $Find,

        [ValidateSet('xlFormulas','xlValues','xlComments','xlCommentsThreaded')]
        [string]$LookIn = 'xlValues',

        [ValidateSet('xlWhole','xlPart')]
        [string]$LookAt = 'xlWhole',

        [switch]$CaseSensitive
    )
    $lookInConstants = @{
        xlFormulas         = -4123
        xlValues           = -4163
        xlComments         = -4144
        xlCommentsThreaded = -4184
    }
    $lookAtConstants = @{
        xlWhole = 1     # Match against the whole of the search text.
        xlPart  = 2     # Match against any part of the search text.
    }

    $excel    = New-Object -ComObject Excel.Application
    $workbook = $excel.Workbooks.Open((Convert-Path $Path))
    foreach ($worksheet in @($workbook.Sheets)) {
        foreach ($searchItem in @($Find)) {
            # Find Method https://learn.microsoft.com/nl-nl/office/vba/api/Excel.Range.Find
            $found = $worksheet.Cells.Find( $searchItem,               # What
                                            [Type]::Missing,           # After
                                            $lookInConstants.$LookIn,  # LookIn
                                            $lookAtConstants.$LookAt,  # LookAt
                                            [Type]::Missing,           # SearchOrder
                                            [Type]::Missing,           # SearchDirection
                                            $CaseSensitive.IsPresent   # MatchCase
                                          )
            if ($found) {
                # Address property https://learn.microsoft.com/nl-nl/office/vba/api/Excel.Range.Address
                $beginAddress = $found.Address(0,0,1,1)
                # First Found Cell
                [PsCustomObject]@{
                    WorkSheet = $worksheet.Name
                    Column    = $found.Column
                    Row       = $found.Row
                    Text      = $found.Text
                    Value     = $found.Value2
                    Address   = $beginAddress
                }
                # Try next finds
                while ($true) {
                    $found = $worksheet.Cells.FindNext($found)
                    if (!$found -or $found.Address(0,0,1,1) -eq $beginAddress) {
                        # exit the loop if FindNext returns nothing or the initially found cell again
                        break
                    }
                    [PsCustomObject]@{
                        WorkSheet = $worksheet.Name
                        Column    = $found.Column
                        Row       = $found.Row
                        Text      = $found.Text
                        Value     = $found.Value2
                        Address   = $found.Address(0,0,1,1)
                    }                 
                }
            }
            else {
                Write-Warning "[$($worksheet.Name)] Value '$searchItem' not found!"
            }
        }
    }
    $workbook.Close($false)
    $excel.Quit()

    [void][System.Runtime.InteropServices.Marshal]::ReleaseComObject($workbook)
    [void][System.Runtime.InteropServices.Marshal]::ReleaseComObject($excel)
    [gc]::Collect()
    [gc]::WaitForPendingFinalizers()
}

用途:

$strings    = 'Alert', 'MESH'
$sourcePath = '\\servername\share\folder\FIGS'

$data = Get-ChildItem -Path $sourcePath -Recurse -Include *.xls, *.xlsx, *.xlsm | 
        ForEach-Object { 
            $_ | Search-Excel -Find $strings
        }
# output on console
$data | Format-Table -AutoSize

# convert to HTML table
$body = $data | ConvertTo-HTMLTable | Out-String
© www.soinside.com 2019 - 2024. All rights reserved.