【问题标题】:Powershell GetEnumerator on HashTable from CSV来自CSV的HashTable上的Powershell GetEnumerator
【发布时间】:2017-05-18 14:45:21
【问题描述】:

我想了解仅打印来自 CSV 的特定 Hashable 值的最佳方法。

CSV 格式如下:

Ticket,Last Updated,Priority,Assigned To,Email
2329,1-12-2017,Medium,Assignee1,assignee1@domain.tld
2417,5-23-2016,Low,Assignee1,assignee1@domain.tld
2416,4-20-2017,Medium,Assignee2,assignee2@domain.tld
2463,8-9-2016,Medium,Assignee2,assignee2@domain.tld
2481,3-4-2017,Low,Assignee3,assignee3@domain.tld
2499,2-22-2017,Medium,Assignee4,assignee4@domain.tld
2500,12-20-2016,High,Assignee5,assignee5@domain.tld
2498,11-30-2016,Medium,Assignee5,assignee5@domain.tld

在一个完美的世界中,假设是我不知道 CSV 标头(因此不知道嵌套的哈希表值)。我将循环创建哈希表,如下面的代码所示:

$import = Import-Csv -Path .\import.csv|
    Group-Object -Property Email -AsHashTable
foreach ($i in $import.GetEnumerator()){
    $html = $($i.Value) | ConvertTo-Html -Head $htmlformat -Body $bodyformat
    $html | Write-Host
}

这很好用。问题是我想从完成的结果中排除 Email 值。

所以我想,虽然不理想,但我知道这个 CSV 的列标题总是会是什么,所以这会起作用吗?:

$import = Import-Csv -Path .\import.csv|
    Group-Object -Property Email -AsHashTable
foreach ($i in $import.GetEnumerator()){
    $html = $($i.Value.'Ticket') + $($i.Value.'Last Updated') + $($i.Value.'Priority') + $($i.Value.'Assigned To') 
    $html | Write-Host
}

您可以看到上面的代码仍然使用Group-Object 来对抗Email 属性,但被排除在输出之外。然而,第二次我添加| ConvertTo-Html -Head $htmlformat -Body $bodyformat 我的所有数据都变成了代表值中字符串的字符数的数字。即使在阅读了很多关于字符串值的ConvertTo-Html 问题之后,作为 PowerShell 中的一个傻瓜,我仍然被卡住了。

总之:

  1. 如果能获得排除 Hashtable 值的代码(这与包含我想要的所有内容的当前代码不同),那就太好了
  2. 更好地理解为什么上面的第一个示例可以毫无问题地使用“ConvertTo-Html”,而第二个则不会。

谢谢。

更新的完整脚本:

下面对康纳的评论中描述了当前存在的问题

$htmlformat  = '<title>Stale Tickets</title>'
$htmlformat += '<style type="text/css">'
$htmlformat += "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"
$htmlformat += "TH{border-width: 1px;padding: 7px;border-style: solid;border-color: black;background-color:thistle}"
$htmlformat += "TD{border-width: 1px;padding: 7px;border-style: solid;border-color: black;background-color:#ffffcc}"
$htmlformat += '</style>'
$bodyformat = '<h3></h3>'
$notice = "<font color='red'><b>This is an automated message.</b></font><br />"

$FromAddress    = "Spiceworks <noreply@domain.tld>"
$ToAddress      = "<My email address for now>"
$Subject        = "You have stale tickets!"
$SMTPserver     = "smtp.whatever.com"

if ((Get-Item "spiceworks_stale_open_ticket_alert.csv").length -gt 0kb)
    {
    $html = Import-Csv -Path .\spiceworks_stale_open_ticket_alert.csv|
    Group-Object -Property Email | ForEach-Object {
        $_.Group | Select-Object * -Exclude 'Email','Assigned To' | ConvertTo-Html -Head $htmlformat -Body $bodyformat
        $html = $html -replace "&lt;","<" -replace "&quot;",'"' -replace "&gt;",">"
        $body = $notice + $html
        Send-MailMessage -from $FromAddress -to $ToAddress -subject $Subject -bodyashtml ($body | Out-String) -priority High -smtpServer $SMTPserver        
        }

    }
else {exit;}

任何偶然发现此问题的人的最终工作迭代:

if ((Get-Item "import.csv").length -gt 0kb)
    {
        Import-Csv -Path .\import.csv|
            Group-Object -Property Email|
            ForEach-Object {
                $Html = $_.Group | Select-Object * -Exclude 'Email','Assigned To' | ConvertTo-Html -Head $HtmlFormat -Body $BodyFormat
                $Html = $Html -replace "&lt;","<" -replace "&quot;",'"' -replace "&gt;",">"
                $Body = $notice + $Html + $notice2
                $Subject        = "Inactive Tickets for " + $_.Group[0].'Assigned To'
                $ToAddress = $_.Name
                Send-MailMessage -from $FromAddress -to $ToAddress -subject $Subject -BodyAsHtml ($Body | Out-String) -Priority High -SmtpServer $SMTPServer
            }   
    }
else {exit;}

【问题讨论】:

    标签: powershell


    【解决方案1】:

    我不确定我是否完全理解您在此处尝试执行的操作,如果您希望生成要发送的票证的 HTML 报告,那么应该这样做(不包括 Email 部分)

    $HTML = Import-Csv ".\SpiceWorks_Tickets" | Select-Object * -ExcludeProperty 'Email' | ConvertTo-Html
    

    使用Select-Object-ExcludeProperty 参数可以让您完全忽略电子邮件。

    ConvertTo-Html 对象接收一组非常有限的对象,它知道如何转换,PsCustomObject(这是Import-Csv 给你的)可以正常工作,但是 Hashtable 不会,所以不是输出内部数据,它会给你System.Collections.Hashtable+KeyCollection,因为这就是它知道如何得到的(我相信它只是调用.ToString()并返回它)

    如果您想遍历 Group-Object 结果的每个成员并将每个值转换为自己的 HTML 表,那么您可以使用以下方法:

    $ImportedCsv | Group-Object -Property Email | ForEach-Object {
        $_.Group | Select-Object * -Exclude 'Email' | ConvertTo-Html
    }
    

    编辑以发送多封电子邮件:

    $ImportedCsv | Group-Object -Property Email | ForEach-Object {
        $ToAddress = $_.Name
        $Body = $_.Group | Select-Object * -Exclude 'Email' | ConvertTo-Html -Head $HtmlFormat -Body $BodyFormat
        Send-MailMessage -From $FromAddress -To $ToAddress -Subject $Subject -BodyAsHtml "$Body" -Priority High -SmtpServer $SMTPServer
    }
    

    【讨论】:

    • 首先感谢您的解释,这一切都开始变得有意义,因此我越来越接近。我对我的原始帖子进行了编辑,最新版本采纳了您的建议。希望它能提供更多的范围。您使用Select-Object * -Exclude 'Email' 的建议非常有效。然而,受让人获得的不是仅包含其票证的格式化表格,而是所有受让人获得每个人票证的多个表格。此外,最终,我将需要在每个循环中使用$_.Group.Email 代替$ToAddress
    • @NickB 我在那里添加了一个 sn-p,它会将每组结果通过电子邮件发送到它们分组的Email
    • 工作得很好,谢谢。为后代添加了上面的最终脚本 - 感谢您的帮助。
    【解决方案2】:

    您可以从数据中删除冗余属性:

    foreach ($key in $import.keys) {
        foreach ($value in $import.$key) {
            $value.PSObject.Properties.Remove("Email")
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-18
      • 1970-01-01
      • 2014-08-09
      • 1970-01-01
      • 2017-04-17
      • 2021-06-21
      • 2016-12-05
      相关资源
      最近更新 更多