【问题标题】:Powershell, Excel Finding string in cell, Color row, delete othersPowershell,Excel在单元格中查找字符串,颜色行,删除其他
【发布时间】:2018-03-23 14:05:19
【问题描述】:

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

  1. 找到空单元格并为其命名,然后将它们标记为黄色。
  2. 查找包含特定单词集的行并将其标记为红色。如果脚本
  3. 如果找不到行中指定的单词,则应删除整行。

到目前为止,这是我的脚本: 任何帮助将不胜感激

在@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

【问题讨论】:

  • 我正在查看它的其余部分,但只要你的进度条移动$i=1 以上ForEach($strComputer in $colComputers) 并在$intRow = $intRow + 1 之后添加$i++(可以缩短为@ 987654327@)
  • 好的,我对你的代码有一般的注释,我想我们可以做你想做的,但我要回家庆祝我继女的生日,所以我得等到明天才能回答.不过,我应该在早上为你发布一些东西,我已经部分解决了。
  • 我没有忘记,但我觉得只是发布一个简短的答案是不对的,即使它是功能性的。有一些很好的学习机会,所以我的帖子即将发布,但由于您的脚本需要重新编写,所以还没有完成。
  • 为什么有人对此投了反对票,我花了很多时间在这上面,而且来自 madtechnician 的 awnser 也被反对了......奇怪。

标签: excel powershell


【解决方案1】:

好的,我猜你是从到处找到的脚本中借用和拼凑出来的,因为它的组合方式似乎有点计划外。就像添加和修改了一些东西,并且没有一个总体规划将它们放在一起。那么,从哪里开始呢?使用进度条,因为我已经解决了这个问题。

进度条

$i=1 移到ForEach($strComputer in $colComputers) 上方并在$intRow = $intRow + 1 之后添加$i++(可以缩短为$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 剩下的内容进行排序,然后将其通过管道传输到剪贴板。

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

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

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

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

那么……我们为什么要改变它?

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

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

寻找并摧毁!

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

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

第二行创建一个字符串,您可以对其进行正则表达式匹配。它获取您的关键字,转义任何特殊字符,将它们与分隔它们的管道连接起来,并将它们括在括号中。在这两行之后$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 查找的主机名和 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}
}

【讨论】:

猜你喜欢
  • 2016-06-15
  • 2021-02-11
  • 1970-01-01
  • 2023-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-08
相关资源
最近更新 更多