Powershell,Excel在单元格中查找字符串,颜色行,删除其他字符串

时间:2014-07-09 20:11:15

标签: excel powershell

我正在寻找一种方法来阅读我的Excel表格,然后;

  1. 找到空单元格并给它们命名,然后将它们标记为黄色。
  2. 查找包含特定单词集的行并将其标记为红色。如果是剧本
  3. 如果找不到行中指定的单词,则应删除整行。
  4. 到目前为止我的脚本是 任何帮助都将非常感谢

    在@TheMadTechician

    的帮助下更新
    #If there is no Out-Clipboard, set it
    If(!(Get-Command Out-Clipboard -ErrorAction SilentlyContinue)){Set-Alias Out-Clipboard "$env:SYSTEMROOT\System32\clip.exe"}
    
    #Get current date
    $Date = get-date -format yyyy-MM-dd
    $Company = "company"
    $Company2 = "company2"
    #Define all files/Paths.
    $Path = "C:\$Company2\BlockedIP"
    md "$Path\HTML\$Date" -Force |Out-Null
    $path2 = "$Path\HTML\$Date"
    $PathWeb = "/HTML/$Date"
    
    #Path = C:/$Company2/BlockedIP
    #Path2 = C:/$Company2/BlockedIP/HTML/2014-07-09
    
    #Define File's used or created in this script.
    $File = "$Path\IP-$Date.txt"
    $FileHtml = "$Path2\IP-$Date.htm"
    $FileXML = "$Path\IP-$Date.xlsx"
    $FileHTMLWeb = "$PathWeb\IP-$date.htm"
    
    #File = C:/$Company2/BlockedIP/IP-2014-07-09.txt
    #FileXML = C:/$Company2/BlockedIP/HTML/2014-07-09/IP-2014-07-09.htm
    #FileHtml = C:/$Company2/BlockedIP/HTML/2014-07-09/IP-2014-07-09.xlsx
    #FileHTMLWeb = PublicIP/HTML/2014-07-09/IP-2014-07-09.htm
    
    
    
    #Define error actions.
    #$erroractionpreference = "SilentlyContinue"
    
    #Get content from given IP list.
    $colComputers = @(get-content $File | Sort -unique)
    $count = $colComputers.Count
        write-output "$Count IP's detected."
    
    #Get DNS Results
    $Progress=1
    $DNSResults = $colComputers | %{
     Write-Progress -Activity "Creating a usable 'Blocked IP' list ($Progress/$count)" -PercentComplete ($Progress/$Count*100) -Status "Please stand by"
    try {
        ($dnsresult = [System.Net.DNS]::GetHostEntry($_))|out-null
    }
    catch {
        $dnsresult = "Fail"
    }
    [PSCustomObject][Ordered]@{
        Source=$_.ToUpper()
        HostName=$dnsresult.HostName
        IPAddress=$dnsresult.AddressList[0].ToString()
    }
    $Progress++
    }
    
    $DNSResults | Sort HostName | ConvertTo-Csv -Delimiter "`t" -NoTypeInformation | Select -Skip 1 | Out-Clipboard
    
    #Open Excel.
    $a = New-Object -comobject Excel.Application
    
    #Since we want this script to look like it's being used without excel I set it's visibility to false.
    $a.visible = $True
    
    #Disable excel confirmations.
    $a.DisplayAlerts = $False
    
    <# 
    # set interactive to false so nothing from excel is shown.
    $Excel.DisplayAlerts = $false
    $Excel.ScreenUpdating = $false
    $Excel.Visible = $false
    $Excel.UserControl = $false
    $Excel.Interactive = $false
    #>
    
    #Create sheets in Excel.
    $b = $a.Workbooks.Add()
    $c = $b.Worksheets.Item(1)
    $c.Activate() | Out-Null
    
    #Create a Title for the first worksheet and adjust the font
    $c.Cells.Item(1,1)= "Blocked IP's $Date"
    $c.Cells.Item(1,1).Font.ColorIndex = 55
    $c.Cells.Item(1,1).Font.Color = 8210719
    $range = $c.Range("a1","e1")
    $range.Style = 'Title'
    $range.Select()
    $range.MergeCells = $true
    $range.VerticalAlignment = -4108
    
    $CounterRow = $Count+5
    #Define subjects.
    $c.Name = "Blocked IP's ($Date)"
    $c.Cells.Item(2,1) = "Given IP"
    $c.Cells.Item(2,2) = "Resolved DNS"
    $c.Cells.Item(2,3) = "Returned IP"
    $c.Cells.Item(2,5) = "$Company"
    $c.Cells.Item($Count+5,1) = "Created by"
    $link = "http://www.$Company"
    $link2 = "https://www.linkedin.com/profile/view?id=#########"
    $r = $c.Range("E2") 
    [void]$c.Hyperlinks.Add($r, $link) 
    $r = $c.Range("A$Counterrow") 
    [void]$c.Hyperlinks.Add($r, $link)
    
    #Define cell formatting from subjects.
    $c.Range("A2:E2").Interior.ColorIndex = 6
    $c.Range("A2:E2").font.size = 13
    $c.Range("A2:E2").Font.ColorIndex = 1
    $c.Range("A2:E2").Font.Bold = $True
    
    #Define html code for Excel save to .htm.
    $xlExcelHTML = 44
    
    #Define the usedrange, excluding header and footer rows
    $e = $c.Range("A3:E$($DNSResults.Count+2)")
    
    #Populate data into spreadsheet
    $DNSResults | Sort HostName | ConvertTo-Csv -Delimiter "`t" -NoTypeInformation | Select -Skip 1 | Out-Clipboard
    #$c.Cells.Item(3,1).Select()
    $c.Paste($e,$false)
    
    $e = $c.Range("A3:C$($DNSResults.Count+2)")
    $c.Paste($e,$false)
    
    $Keywords = "Google","thenetworkfactory","HappyTreeFriends"
    $Filter = "($(($Keywords|%{[RegEx]::Escape($_)}) -join "|"))"
    
    $DNSResults | Where{$_ -match $filter} | Sort HostName | ConvertTo-Csv -Delimiter "`t" -NoTypeInformation | Select -Skip 1 | Out-Clipboard
    
    
    ForEach($Cell in $e){
    If([String]::IsNullOrWhitespace($Cell.value2)){$Cell.interior.colorindex=6}
    }
    
    #Define the usedrange for autofitting.
    $d = $c.UsedRange
    
    #Set background color for the IP list.
    $E.interior.colorindex = 15
    
    #Define borders here.
    $xlOpenXMLWorkbook = 51
    $xlAutomatic=-4105
    $xlBottom = -4107
    $xlCenter = -4108
    $xlRight = -4152
    $xlContext = -5002
    $xlContinuous=1
    $xlDiagonalDown=5
    $xlDiagonalUp=6
    $xlEdgeBottom=9
    $xlEdgeLeft=7
    $xlEdgeRight=10
    $xlEdgeTop=8
    $xlInsideHorizontal=12
    $xlInsideVertical=11
    $xlNone=-4142
    $xlThin=2 
    $selection = $c.range("A3:C$($DNSResults.Count+2)")
    $selection.select() |out-null
    $selection.HorizontalAlignment = $xlRight
    $selection.VerticalAlignment = $xlBottom
    $selection.WrapText = $false
    $selection.Orientation = 0
    $selection.AddIndent = $false
    $selection.IndentLevel = 0
    $selection.ShrinkToFit = $false
    $selection.ReadingOrder = $xlContext
    $selection.MergeCells = $false
    $selection.Borders.Item($xlInsideHorizontal).Weight = $xlThin
    
    
    
    #Make everything fit in it's cell.
    $d.EntireColumn.AutoFit() | Out-Null
    
    #Save the file as .xlsx on every placed IP to ensure the file is not lost due to any reason.
    $b.SaveAs("$FileXML")
    
    #Clear screen on every checked IP to remove the 'True' statement.
    #cls
    #
    
    
    #Save final result as a .htm file
    $b.SaveAs("$FileHTML",$xlExcelHTML)
    
    #Close and quit Excel.
    $b.Close()
    get-process *Excel* | Stop-Process -force
    
    #Move .txt file to the correct HTML folder.
    move-item $file $path2 -Force
    
    #Move .xlsx file to the correct HTML folder.
    move-item $filexml $path2 -Force
    
    #Declare XLSX file for mail
    $MailXML = "$path2\IP-$Date.xlsx"
    
    #Clear screen, again. (Let's keep things tidy.)
    #cls
    
    #Variables for public IP
    # I am defining website url in a variable
    $url = "http://checkip.dyndns.com" 
    # Creating a new .Net Object names a System.Net.Webclient
    $webclient = New-Object System.Net.WebClient
    # In this new webdownlader object we are telling $webclient to download the
    # url $url 
    $IpPublic = $webclient.DownloadString($url)
    # Just a simple text manuplation to get the ipadress form downloaded URL
    # If you want to know what it contain try to see the variable $IpPublic
    $IpPublic2 = $IpPublic.ToString()
    $ipPublic3 = $IpPublic2.Split(" ")
    $ipPublic4 = $ipPublic3[5]
    $ipPublic5 = $ipPublic4.replace("</body>","")
    $FinalIPAddress = $ipPublic5.replace("</html>","")
    $ipLocal = (Get-WmiObject -class win32_NetworkAdapterConfiguration -Filter 'ipenabled = "true"').ipaddress[0]
    
    #Variables e-mail.
    $From = "Blocked IP <r.van.tour@$Company>"
    $To = "IT Dept <r.van.tour@$Company>"
    $CC = "Someone <$Company2@$Company"
    $Subject = "Blocked IPs for $date ($Count Total)"
    #The href should point to the htm file in your iis/apache folder.
    $WebLink = $FinalIPAddress+$FileHtmlWeb
    $here = "<a href='http://$Weblink'><b>Here</b></a>"
    #Define the body of your e-mail, in this case it displays a message and shows the server it is send from with it's local IP.
    #A link to the .htm file, how many IP's were blocked and the date of the message.
    $Body = "<!DOCTYPE html><html><head> <title>Blocked IP's $Date</title></head><header><h1>Blocked IP</h1><p><time pubdate datetime='$date'></time></p></header><br>" 
    $body += "<body>Dear <font color=black>$to</font>,<br><br>"
    $body += "This is an automated message generated by server: <font color=red><b>$env:COMPUTERNAME, $IPLocal.</b></font><br><br>"
    $body += "Click <font color=red><b>$here</b></font> to see the Blocked IP report for $date containing $count IP's.<br>"
    $body += "Or see the attachment to open it in Excel.<br></body></html>"
    
    
    #Clear screen, again. (Let's keep things tidy.)
    #cls
    
    #Send output as e-mail.
    $SMTPServer = "smtp.gmail.com"
    $SMTPPort = "587"
    $Username = "##@gmail.com"
    $Password = "##"
    $message = New-Object System.Net.Mail.MailMessage
    $message.IsBodyHTML = $true
    $message.ReplyTo = $From
    $message.Sender = $From
    $message.subject = $subject
    $message.body = $body
    $message.to.add($to)
    $message.from = $From
    $message.attachments.add($MailXML)
    $smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort);
    $smtp.EnableSSL = $true
    $smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);
    $smtp.send($message)
    
    #Create a function to relase Com object at end of script.
    function Release-Ref ($ref) { 
    ([System.Runtime.InteropServices.Marshal]::ReleaseComObject( 
    [System.__ComObject]$ref) -gt 0) 
    [System.GC]::Collect() 
    [System.GC]::WaitForPendingFinalizers() 
                            }
    
    #Release COM Object
    [System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$a) | Out-Null
    
    #Clear screen for the final time. (Let's keep things tidy.)
    #cls
    
    #Exit powershell 
    exit
    

    @TheMadTechnician

    脚本的这一部分似乎存在问题,其中未解析的IP地址无法在$ DNSResults中显示

    $Keywords = "Google","Cloudflare","Cloud","Ping","Easy-    Voyage","McAfee","Pingdom","Panopta","Scoot","Uniglobe"
    $Filter = "($(($Keywords|%{[RegEx]::Escape($_)}) -join "|"))"
    
    #Define error actions.
    #$erroractionpreference = "SilentlyContinue"
    
    #Get content from given IP list.
    $colComputers = @(get-content $File | Sort -unique)
    $SourceCount = $colComputers.Count
    write-output "$SourceCount IP's detected."
    
    #Get DNS Results
    $Progress=1
    $DNSResults = $colComputers | %{
    Write-Progress -Activity "Creating a usable 'Blocked IP' list ($Progress/$sourcecount)" -PercentComplete ($Progress/$sourceCount*100) -Status "Please stand by"
    try {
        ($dnsresult = [System.Net.DNS]::GetHostEntry($_))|out-null
    }
    catch {
        $dnsresult = "Fail"
    }
    [PSCustomObject][Ordered]@{
        Source=$_.ToUpper()
        HostName=$dnsresult.HostName
        IPAddress=$dnsresult.AddressList[0].ToString()
    }
    $Progress++
    }
    
    $count = ($DNSResults|?{$_ -match $filter}).count
    

1 个答案:

答案 0 :(得分:2)

好吧,我猜你已经从全部发现的脚本中借用并拼凑了这些,因为它放在一起的方式似乎有点无计划。就像添加和修改的东西一样,并没有一个总体规划可以将它们整合在一起。那么,从哪里开始呢?随着进度条,我已经解决了这个问题。

进度条

$i=1移到ForEach($strComputer in $colComputers)之上,然后在$i++之后添加$intRow = $intRow + 1(可以缩短为$intRow++)。但我们已经知道了。这种方式变得没有实际意义,因为我已经重写了一些你的脚本,但实际上你会在接下来的ForEach循环中看到它。

ForEach循环

接下来,你的ForEach循环。男孩,那里很吵。你正在做它做的事情,一切都结束,真的只需要在一切都完成之后完成。那么,循环后我们应该做些什么呢?让我们从几乎所有事情开始吧。细胞格式化?后来。填充细胞?后来。排序?后来。调整列宽?后来。保存文件?后来!

那么,这又是什么让我们陷入困境?实际上并不多,它留下的是进度条和检查DNS条目。为什么这样?因为我们可以在PowerShell中使用您想要的数据创建数组,对数据进行排序,仅从数组中选择要使用的字段,然后一次粘贴所有数据而不是一次粘贴一条记录,并执行所有操作之后的格式。实际上,格式化可能更好,而不是检查单元格是否为空白并将它们着色为红色只是将条件格式应用于它们,这样如果它们为空白它们会显示红色,并让Excel完成工作你。

这将使脚本运行得更快,因为您没有多次执行相同的工作,并且正在使用PowerShell中的原始数据而不是让Excel执行此操作。我最终将你的ForEach循环减少到几行:

#Get DNS Results
$Progress=1
$DNSResults = $colComputers | %{
     Write-Progress -Activity "Creating a usable 'Blocked IP' list ($Progress/$count)" -PercentComplete ($Progress/$Count*100) -Status "Please stand by"
    try {
        ($dnsresult = [System.Net.DNS]::GetHostEntry($_))|out-null
    }
    catch {
        $dnsresult = "Fail"
    }
    [PSCustomObject][Ordered]@{
        Source=$_.ToUpper()
        HostName=$dnsresult.HostName
        IPAddress=$dnsresult.AddressList[0].ToString()
    }
    $Progress++
}

这将遍历条目并创建一个自定义对象数组,这些对象具有3个属性,这些属性是电子表格中所需的3个单元格。

Excel设置

好的,就格式化和注入简单文本而言,你显然已经掌握了一些东西,所以我现在要对你的标题设置进行釉面处理,并将处理后的数据放到电子表格中。

对于数据数组(例如您放入的计算机/主机名/ IP数据阵列),可以更容易地将其作为制表符分隔的CSV对象粘贴到Excel中。 Out-Clipboard不是标准的PowerShell cmdlet,即使我认为它应该是。另一方面,Clip.exe标配Windows,因此我们可以为它设置一个别名(如果你有PowerShell社区扩展,这已经为你完成了)。我把它放在脚本的顶部以使其不受影响。通常情况下,如果我需要设置这样的别名,我会在脚本中设置的任何函数之后立即执行。它检查你是否有Out-Clipboard,如果你没有设置Clip.exe到Out-Clipboard的别名。

If(!(Get-Command Out-Clipboard -ErrorAction SilentlyContinue)){Set-Alias Out-Clipboard "$env:SYSTEMROOT\System32\clip.exe"}

现在我们可以把东西送到剪贴板,这对于我们下一步想要做的事情来说非常方便。我们将获取数组并将其转换为制表符分隔的CSV(没有类型信息),跳过第一个条目(标题行),对HostName留下的内容进行排序,并将其传送到剪贴板。 / p>

$DNSResults | Sort HostName | ConvertTo-Csv -Delimiter "`t" -NoTypeInformation | Select -Skip 1 | Out-Clipboard

现在我们只需将其粘贴到Excel中即可。为此,我们需要一个范围对象来指定目标,因此我将其设置为,然后我们使用WorkSheet对象的粘贴(范围,链接)方法。不要担心链接部分,我们将使用$ false布尔值,因为我们不会将粘贴的数据链接到数据源以进行动态更新。这看起来像:

$e = $c.Range("A3:E$($DNSResults.Count+2)")
$c.Paste($e,$false)

然后我们继续设置结果的颜色以及格式的其余部分。

那么......为什么我们改变它?

所以,我最喜欢的叔叔总是告诉我成长&#34;如果它没有破坏,就不要修理它&#34; 。你的脚本做了你想要的,所以如果它没有被破坏,为什么我要改进呢?这些变化并不是很大,它实际上是关于加快速度并一次插入所有内容而不是一次插入所有内容,但最重要的是现在我们可以在插入Excel之前在PowerShell中进行过滤,并且这将我们带到你原来的问题:

  • 将空白单元格设置为黄色。
  • 将行与关键字匹配,删除所有其他行。

寻求并摧毁!

我们会在一秒钟内找到空白,但删除那些没有关键词的行现在很容易。不要删除它们,只是不要插入它们开始!设置要过滤的单词列表很容易,然后在我们导出到剪贴板时只包含带有这些单词的记录。

$Keywords = "Google","Facebook","HappyTreeFriends"
$Filter = "($(($Keywords|%{[RegEx]::Escape($_)}) -join "|"))"

第二行创建一个字符串,您可以对其进行RegEx匹配。它接受你的关键字,逃避任何特殊字符,用分隔它们的管道将它们连接起来,并将它们括在括号中。在这两行之后$Filter = (Google|Facebook|HappyTreeFriends)。然后在要将数据发送到剪贴板的行上添加一个Where子句:

$DNSResults | Where{$_ -match $filter} | Sort HostName | ConvertTo-Csv -Delimiter "`t" -NoTypeInformation | Select -Skip 1 | Out-Clipboard

这样,只有具有您列入黑名单的单词的记录才会插入到Excel中,您不必担心返回并删除行。您希望的行将关键字突出显示为红色?只需对它们进行着色(现在你将它们设置为颜色索引15,灰色,只需将其更改为3并且它们将是红色),因为它们应该是那里唯一的东西。

缺少什么?

空白单元格很难被发现,特别是一旦进行了一些格式化,并且具有较少定义的单元格边框。在这种情况下找到空单元格非常简单。我们已经有了$ e,这是一个范围对象,包括我们刚插入Excel的所有数据,甚至是空白单元格。范围对象基本上是一组单元格,每个单元格都有自己的属性,如位置(行,列),格式,值等。您可以做的很简单:

#If there is no Out-Clipboard, set it
If(!(Get-Command Out-Clipboard -ErrorAction SilentlyContinue)){Set-Alias Out-Clipboard "$env:SYSTEMROOT\System32\clip.exe"}

#Get current date
$Date = get-date -format yyyy-MM-dd
$Company = "company"
$Company2 = "company2"
#Define all files/Paths.
$Path = "C:\$Company2\BlockedIP"
md "$Path\HTML\$Date" -Force |Out-Null
$path2 = "$Path\HTML\$Date"
$PathWeb = "/HTML/$Date"

#Path = C:/$Company2/BlockedIP
#Path2 = C:/$Company2/BlockedIP/HTML/2014-07-09

#Define File's used or created in this script.
$File = "$Path\IP-$Date.txt"
$FileHtml = "$Path2\IP-$Date.htm"
$FileXML = "$Path\IP-$Date.xlsx"
$FileHTMLWeb = "$PathWeb\IP-$date.htm"

#File = C:/$Company2/BlockedIP/IP-2014-07-09.txt
#FileXML = C:/$Company2/BlockedIP/HTML/2014-07-09/IP-2014-07-09.htm
#FileHtml = C:/$Company2/BlockedIP/HTML/2014-07-09/IP-2014-07-09.xlsx
#FileHTMLWeb = PublicIP/HTML/2014-07-09/IP-2014-07-09.htm

$Keywords = "Google","thenetworkfactory"
$Filter = "($(($Keywords|%{[RegEx]::Escape($_)}) -join "|"))"

#Define error actions.
#$erroractionpreference = "SilentlyContinue"

#Get content from given IP list.
$colComputers = @(get-content $File | Sort -unique)
$SourceCount = $colComputers.Count
    write-output "$Count IP's detected."

#Get DNS Results
$Progress=1
$DNSResults = $colComputers | %{
 Write-Progress -Activity "Creating a usable 'Blocked IP' list ($Progress/$sourcecount)" -PercentComplete ($Progress/$sourceCount*100) -Status "Please stand by"
try {
    ($dnsresult = [System.Net.DNS]::GetHostEntry($_))|out-null
}
catch {
    $dnsresult = "Fail"
}
[PSCustomObject][Ordered]@{
    Source=$_.ToUpper()
    HostName=$dnsresult.HostName
    IPAddress=$dnsresult.AddressList[0].ToString()
}
$Progress++
}

$count = ($DNSResults|?{$_ -match $filter}).count

#Open Excel.
$a = New-Object -comobject Excel.Application

#Since we want this script to look like it's being used without excel I set it's visibility to false.
$a.visible = $True

#Disable excel confirmations.
$a.DisplayAlerts = $False

<# 
# set interactive to false so nothing from excel is shown.
$Excel.DisplayAlerts = $false
$Excel.ScreenUpdating = $false
$Excel.Visible = $false
$Excel.UserControl = $false
$Excel.Interactive = $false
#>

#Create sheets in Excel.
$b = $a.Workbooks.Add()
$c = $b.Worksheets.Item(1)
$c.Activate() | Out-Null

#Create a Title for the first worksheet and adjust the font
$c.Cells.Item(1,1)= "Blocked IP's $Date"
$c.Cells.Item(1,1).Font.ColorIndex = 55
$c.Cells.Item(1,1).Font.Color = 8210719
$range = $c.Range("a1","e1")
$range.Style = 'Title'
$range.Select()
$range.MergeCells = $true
$range.VerticalAlignment = -4108

$CounterRow = $Count+5
#Define subjects.
$c.Name = "Blocked IP's ($Date)"
$c.Cells.Item(2,1) = "Given IP"
$c.Cells.Item(2,2) = "Resolved DNS"
$c.Cells.Item(2,3) = "Returned IP"
$c.Cells.Item(2,5) = "$Company"
$c.Cells.Item($Count+5,1) = "Created by"
$link = "http://www.$Company"
$link2 = "https://www.linkedin.com/profile/view?id=#########"
$r = $c.Range("E2") 
[void]$c.Hyperlinks.Add($r, $link) 
$r = $c.Range("A$Counterrow") 
[void]$c.Hyperlinks.Add($r, $link)

#Define cell formatting from subjects.
$c.Range("A2:E2").Interior.ColorIndex = 6
$c.Range("A2:E2").font.size = 13
$c.Range("A2:E2").Font.ColorIndex = 1
$c.Range("A2:E2").Font.Bold = $True

#Define html code for Excel save to .htm.
$xlExcelHTML = 44

#Define the usedrange, excluding header and footer rows
$e = $c.Range("A3:E$(2+$Count)")

#Populate data into spreadsheet
$DNSResults | Where{$_ -match $filter} | Sort HostName | ConvertTo-Csv -Delimiter "`t" -NoTypeInformation | Select -Skip 1 | Out-Clipboard
#$c.Cells.Item(3,1).Select()
$c.Paste($e,$false)

ForEach($Cell in $e){
If([String]::IsNullOrWhitespace($Cell.value2)){$Cell.interior.colorindex=6}
}

#Define the usedrange for autofitting.
$d = $c.UsedRange

#Set background color for the IP list.
$E.interior.colorindex = 15

#Define borders here.
$xlOpenXMLWorkbook = 51
$xlAutomatic=-4105
$xlBottom = -4107
$xlCenter = -4108
$xlRight = -4152
$xlContext = -5002
$xlContinuous=1
$xlDiagonalDown=5
$xlDiagonalUp=6
$xlEdgeBottom=9
$xlEdgeLeft=7
$xlEdgeRight=10
$xlEdgeTop=8
$xlInsideHorizontal=12
$xlInsideVertical=11
$xlNone=-4142
$xlThin=2 
$selection = $c.range("A3:C$($DNSResults.Count+2)")
$selection.select() |out-null
$selection.HorizontalAlignment = $xlRight
$selection.VerticalAlignment = $xlBottom
$selection.WrapText = $false
$selection.Orientation = 0
$selection.AddIndent = $false
$selection.IndentLevel = 0
$selection.ShrinkToFit = $false
$selection.ReadingOrder = $xlContext
$selection.MergeCells = $false
$selection.Borders.Item($xlInsideHorizontal).Weight = $xlThin



#Make everything fit in it's cell.
$d.EntireColumn.AutoFit() | Out-Null

#Save the file as .xlsx on every placed IP to ensure the file is not lost due to any reason.
$b.SaveAs("$FileXML")

#Clear screen on every checked IP to remove the 'True' statement.
#cls
#


#Save final result as a .htm file
$b.SaveAs("$FileHTML",$xlExcelHTML)

#Close and quit Excel.
$b.Close()
get-process *Excel* | Stop-Process -force

#Move .txt file to the correct HTML folder.
move-item $file $path2 -Force

#Move .xlsx file to the correct HTML folder.
move-item $filexml $path2 -Force

#Declare XLSX file for mail
$MailXML = "$path2\IP-$Date.xlsx"

#Clear screen, again. (Let's keep things tidy.)
#cls

#Variables for public IP
# I am defining website url in a variable
$url = "http://checkip.dyndns.com" 
# Creating a new .Net Object names a System.Net.Webclient
$webclient = New-Object System.Net.WebClient
# In this new webdownlader object we are telling $webclient to download the
# url $url 
$IpPublic = $webclient.DownloadString($url)
# Just a simple text manuplation to get the ipadress form downloaded URL
# If you want to know what it contain try to see the variable $IpPublic
$IpPublic2 = $IpPublic.ToString()
$ipPublic3 = $IpPublic2.Split(" ")
$ipPublic4 = $ipPublic3[5]
$ipPublic5 = $ipPublic4.replace("</body>","")
$FinalIPAddress = $ipPublic5.replace("</html>","")
$ipLocal = (Get-WmiObject -class win32_NetworkAdapterConfiguration -Filter 'ipenabled = "true"').ipaddress[0]

#Variables e-mail.
$From = "Blocked IP <r.van.tour@$Company>"
$To = "IT Dept <r.van.tour@$Company>"
$CC = "Someone <$Company2@$Company"
$Subject = "Blocked IPs for $date ($Count Total)"
#The href should point to the htm file in your iis/apache folder.
$WebLink = $FinalIPAddress+$FileHtmlWeb
$here = "<a href='http://$Weblink'><b>Here</b></a>"
#Define the body of your e-mail, in this case it displays a message and shows the server it is send from with it's local IP.
#A link to the .htm file, how many IP's were blocked and the date of the message.
$Body = "<!DOCTYPE html><html><head> <title>Blocked IP's $Date</title></head><header><h1>Blocked IP</h1><p><time pubdate datetime='$date'></time></p></header><br>" 
$body += "<body>Dear <font color=black>$to</font>,<br><br>"
$body += "This is an automated message generated by server: <font color=red><b>$env:COMPUTERNAME, $IPLocal.</b></font><br><br>"
$body += "Click <font color=red><b>$here</b></font> to see the Blocked IP report for $date containing $count IP's.<br>"
$body += "Or see the attachment to open it in Excel.<br></body></html>"


#Clear screen, again. (Let's keep things tidy.)
#cls

#Send output as e-mail.
$SMTPServer = "smtp.gmail.com"
$SMTPPort = "587"
$Username = "##@gmail.com"
$Password = "##"
$message = New-Object System.Net.Mail.MailMessage
$message.IsBodyHTML = $true
$message.ReplyTo = $From
$message.Sender = $From
$message.subject = $subject
$message.body = $body
$message.to.add($to)
$message.from = $From
$message.attachments.add($MailXML)
$smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort);
$smtp.EnableSSL = $true
$smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);
$smtp.send($message)

#Create a function to relase Com object at end of script.
function Release-Ref ($ref) { 
([System.Runtime.InteropServices.Marshal]::ReleaseComObject( 
[System.__ComObject]$ref) -gt 0) 
[System.GC]::Collect() 
[System.GC]::WaitForPendingFinalizers() 
                        }

#Release COM Object
[System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$a) | Out-Null

#Clear screen for the final time. (Let's keep things tidy.)
#cls

#Exit powershell 
exit

编辑:我发现您的脚本存在问题。您没有更新要复制到剪贴板的行,在脚本已经粘贴到Excel之后,您刚刚在脚本中添加了行,因此您添加的代码实际上没有做任何事情。我对您的代码进行了一些更新(以更好地处理记录计数,并正确过滤),并更新了上述脚本。

Edit2:这篇文章变得越来越长。好的,所以要包括我修改了一些内容的所有条目。首先查找DNS结果的ForEach循环,我在尝试填充之前修改了对象创建行以检查它们是否存在,因此它会停止在没有DNS查找的一个或两个HostName和IP地址的事情上抛出错误

[PSCustomObject][Ordered]@{
    Source=$_.ToUpper()
    HostName=$(if(!([string]::IsNullOrEmpty($dnsresult.HostName))){$dnsresult.HostName})
    IPAddress=$(if(!([string]::IsNullOrEmpty($dnsresult.AddressList))){$dnsresult.AddressList[0].ToString()})
}

然后我将结果分成三个类别:主机名匹配关键字,主机名不匹配关键字,没有主机名(也改变$ count wince我们包括所有内容)。

$DNSWithKeyword = $DNSResults | ?{$_.HostName -match $Filter}
$DNSNoKeyword = $DNSResults | ?{!($_.HostName -match $Filter) -and !([string]::IsNullOrEmpty($_.HostName))}
$DNSLookupFailed = $DNSResults | ?{([string]::IsNullOrEmpty($_.HostName))}
#$count = ($DNSResults|?{$_ -match $filter}).count
$count = $SourceCount

然后向下定义使用范围的方法我为每个类别添加了一个,而不是只有一个复制/粘贴我做三个所以首先匹配关键字,按主机名排序,然后没有按主机名排序的关键字,以及那些没有主机名的人。然后我按照部分给每个颜色着色,然后又回来并再次将空白细胞染成黄色。

#Define the usedrange, excluding header and footer rows
$KeyRange = $c.Range("A3:E$(2+$DNSWithKeyword.Count)")
$NoKeyRange = $c.Range("A$(2+$DNSWithKeyword.Count+1):E$(2+$DNSWithKeyword.Count+$DNSNoKeyword.Count)")
$NoDNSRange = $c.Range("A$(2+$DNSWithKeyword.Count+$DNSNoKeyword.Count+1):E$(2+$DNSWithKeyword.Count+$DNSNoKeyword.Count+$DNSLookupFailed.Count)")
$e = $c.Range("A3:E$(2+$Count)")

#Populate data into spreadsheet
$DNSWithKeyword | Sort HostName | ConvertTo-Csv -Delimiter "`t" -NoTypeInformation | Select -Skip 1 | Out-Clipboard
$c.Paste($KeyRange,$false)
$DNSNoKeyword | Sort HostName | ConvertTo-Csv -Delimiter "`t" -NoTypeInformation | Select -Skip 1 | Out-Clipboard
$c.Paste($NoKeyRange,$false)
$DNSLookupFailed | ConvertTo-Csv -Delimiter "`t" -NoTypeInformation | Select -Skip 1 | Out-Clipboard
$c.Paste($NoDNSRange,$false)

#Define the usedrange for autofitting.
$d = $c.UsedRange

#Set background color for the IP list.
$KeyRange.interior.colorindex = 3
$NoKeyRange.interior.colorindex = 15
$NoDNSRange.interior.colorindex = 14

ForEach($Cell in $e){
If([String]::IsNullOrWhitespace($Cell.value2)){$Cell.interior.colorindex=6}
}