【问题标题】:Extracting Tables from .CSV for Use in Email从 .CSV 中提取表格以用于电子邮件
【发布时间】:2023-04-05 18:37:01
【问题描述】:

我有一个 .csv 文件,其中包含超过 1000 条我工作的公司前雇员的条目,我正在尝试按员工将其拆分为可以插入电子邮件模板的格式。更糟糕的是,许多(但不是全部)员工有不止一个条目,并且 .csv 包含大量信息,这对于我将向其发送电子邮件的人来说是完全不必要的。理想情况下,我想排除这些列,但我遇到了很多困难。在我看来,format-table 将是我需要的 cmdlet,但我不能 100% 确定。到目前为止,我已经尝试过:

import-csv C:\filepath\xx.csv | format-table -groupby (key value)

它确实返回了按我想要的方式组织的信息,但是我不知道如何从那里拆分信息,所以我只能发送特定员工的信息。如前所述,这还包括相当多的无关信息。我也试过:

import-csv C:\filepath\xx.csv | format-table -groupby (key value) -property (properties I want,separated by commas)

但是,这仍然返回相同的无关信息。我还尝试使用 foreach 循环遍历 .csv,将我想要的信息存储在变量中,然后将这些变量存储在一个数组中,然后将该数组通过管道传输到格式表中,这会导致一团糟。我还尝试将 .csv 放入按我想要的键值分组的哈希表中,但这会导致其余信息被放入字符串中。我相信我应该能够使用正则表达式拆分这个字符串,但是我对正则表达式一点也不熟悉,也不知道从哪里开始。在这一点上,我很困惑。任何帮助将不胜感激。

编辑

在遵循@4c74356b41 的建议(对此我非常感谢)之后,我能够输出仅包含相关信息的表格列表。但是,我仍然无法将此表列表拆分为我需要的单个表。我目前有一个 .txt 文件,我将其用作模板,我想为各个用户添加表格。到目前为止,我已经成功使用 get-content 来检索 .txt 的内容,-replace 从原始 .csv 中的信息(例如名称、经理等)替换模板上的其他几个字段,然后输出-文件将编辑后的模板存储到临时文件中,然后将其作为草稿保存到 Outlook。我试图在前一个 foreach 循环中添加另一个 foreach 循环,以将表添加到模板中,但这会返回带有“Microsoft.PowerShell.Commands.Internal.Format.FormatStartData”行的模板来代替表。它还为每个条目创建一个草稿,而不仅仅是为每个唯一用户 ID 创建一个草稿。这是我到目前为止的所有代码:

$olFolderDrafts = 16
$ol = New-Object -comObject Outlook.Application 
$ns = $ol.GetNameSpace("MAPI")
$file= import-csv H:\filepath\term_rep.csv
$data= import-csv H:\filepath\term_rep.csv | select-object "Inactive Emp Name","User ID","Loc","Equipment Descr","Tag Number","Serial Number"
$table= $data | Format-Table -GroupBy "User ID"
foreach($i in $file)
    {$user = $i | select-object -expandproperty "Inactive Emp Name"
    $uid= $i | select-object -expandproperty "User ID"
    $manager = $i | Select-Object -expandproperty "Manager"
    $loc= $i | select -ExpandProperty "Loc"
    $tagnum= $i | select -ExpandProperty "Tag Number"
    $sernum= $i | select -ExpandProperty "Serial Number"
    $path="C:\filepath\term_email.txt"
    $newpath = [system.io.path]::GetTempFileName() 
    (Get-content $path) -replace "USER_NAME",$user `
    -replace "USER_ID",$uid | out-file $newpath
    foreach($id in $table){
        (Get-Content $newpath) -replace "EQUIPMENT_LIST", $id | out-file $newpath
    }
    $subject="Equipment for user $uid"
    $body= get-content $newpath
    $mail = $ol.CreateItem(0)
    $mail.To = $manager 
    $mail.CC = $null
    $mail.Subject = $subject  
    $mail.Body = $body -join "`n"
    $mail.save()}

【问题讨论】:

  • 那是另一个问题,但通常他们在这里遇到的问题是在使用Format-Table 格式化数据后尝试对数据进行操作。格式化任何东西都应该是管道中的最后一个操作
  • 我不同意这是一个单独的问题。我最初的问题是如何以有用的格式格式化和分离这个 .csv 中的信息。您的建议对格式化部分很有帮助,但对分离没有帮助。
  • 事实上,他是对的,有点。我认为这是一个糟糕的措辞选择。不是你的错,但“格式”这个词在 PowerShell 中是一种特殊的词,因为它指的是用于格式化数据以进行演示的许多 cmdlet,而不是用于进一步使用。 Import-CSV 的本质是创建一个可用于创建电子邮件的表。 Format-Table cmdlet 只是以人类易于使用的格式显示该表。如果您想捕获并进一步使用该点之后的数据,您真的需要停止使用Format-Table
  • 如果我的问题误导了我,我深表歉意,我对 powershell 还是很陌生。如果有更好的方法,我很乐意停止与 Format-Table 的斗争并以另一种方式来做。
  • @TheMadTechnician 我编辑了问题的标题以更好地适应。如果我应该进行任何其他编辑以使问题更准确,请告诉我:)

标签: powershell csv powershell-5.0


【解决方案1】:

为了减少干扰和重复,我会找到一个特定于用户的列,例如用户名或电子邮件。然后按此分组,然后选择每个组中的第一个项目。然后你可以通过管道连接到Select 以减少来自无关列的噪音。比如:

import-csv C:\filepath\xx.csv | Group UserName | ForEach{$_.Group[0]} | Select FirstName,LastName,Email,UserName,SeparationDate 

然后您可以随心所欲地使用它...管道到另一个 ForEach 循环以一次处理每个记录,或将其管道到 Export-CSV 以生成一个新的 CSV 以减少混乱,您可以一起工作。您甚至可以让 PowerShell 为您创建电子邮件,具体取决于您想要获得的效果。

如果您需要进一步的帮助,请通过示例更新您的问题,说明您希望的输出是什么,或者您希望通过每个条目完成什么。

编辑:好的,归根结底,您需要为与特定用户匹配的任何记录插入一个事物表,以便您可以从他们的电子邮件中取回他们的东西离职后的经理。酷,我们可以做到。首先,您使用的是 Outlook ComObject,并以这种方式生成您的电子邮件。太棒了,我自己做了,你可以用这种方式做一些很棒的事情!我强烈推荐在这里使用 HTML。它使电子邮件看起来更专业,并让我们在电子邮件中插入一个漂亮的表格,而不是一些格式化文本,因为一旦在电子邮件中出现空格,就会看起来很有趣。

所以,让我们从这个问题中恢复过来,重做您的电子邮件模板。弹出打开 MS Word 并打开您的模板。现在,转到文件并另存为。选择“Web Page, Filtered”作为您的文档类型,并将其命名为您已有的名称。

因此,与其加载列表两次,然后导出,然后等等等等,我们将缩短一些内容。我们加载您的 CSV 一次。就此而言,我们不需要为每个用户读取一次电子邮件正文,因此我们也只需在循环之前将其加载一次即可。然后我们使用-Unique 开关将用户ID 字段传递给Select-Object,这样我们每个用户只会生成一封电子邮件。所以,到那里的脚本看起来像这样:

$olFolderDrafts = 16
$ol = New-Object -comObject Outlook.Application 
$ns = $ol.GetNameSpace("MAPI")
$file= import-csv H:\filepath\term_rep.csv
$path="C:\filepath\term_email.txt"
$body = (Get-content $path) -join "`n"
foreach($i in ($file.'User ID'|Select -Unique))
    {

现在,无需像您之前那样分配所有这些变量,因此我将跳过该部分。所以我们将找到当前用户的第一个实例,并将其保存到一个变量中。

    $User = $File|Where{$_.'User ID' -eq $i}|Select -First 1

一旦我们知道了,我们将在列表中找到他们的所有记录,只选择您感兴趣的属性,然后使用ConvertTo-HTML 将输出转换为 HTML 表格。

    $Equip = $File|Where{$_.'User ID' -eq $i}|select-object "Inactive Emp Name","User ID","Loc","Equipment Descr","Tag Number","Serial Number"|ConvertTo-Html -Property '*' -As Table -Fragment

现在这是一条很长的路线,但其中大部分只是选择正确的属性。魔术发生在最后一点,我们告诉它将数据转换为 HTML。具体来说,我们希望所有内容(由-Property '*' 指定),我们希望将其转换为表格,并且这只是一个片段,因此它不会尝试将所有前面和后面的标签放在那里(所以没有<HTML></HTML> 类型标签,因为它被注入到现有 HTML 的中间。)

然后我们进行替换,发送电子邮件,分配属性,yada,yada,yada,你几乎已经拥有了所有这些......

    $HTMLbody = $body -replace "USER_NAME",$user.'Inactive Emp Name' -replace "USER_ID",$user.'User ID' -replace "EQUIPMENT_LIST", $Equip
    $subject="Equipment for user " + $User.'User ID'
    $mail = $ol.CreateItem(0)
    $mail.To = $User.Manager 
    $mail.Subject = $subject  
    $mail.HTMLBody = $HTMLbody
    $mail.save()
    }

保存,完成!循环到下一个用户,然后重复。所以把它们放在一起,你会得到:

$olFolderDrafts = 16
$ol = New-Object -comObject Outlook.Application 
$ns = $ol.GetNameSpace("MAPI")
$file= import-csv H:\filepath\term_rep.csv
$path="C:\temp\email.htm"
$body = (Get-content $path) -join "`n"
foreach($i in ($file.'User ID'|Select -Unique))
    {
    $User = $File|Where{$_.'User ID' -eq $i}|Select -First 1
    $Equip = $File|Where{$_.'User ID' -eq $i}|select-object "Inactive Emp Name","User ID","Loc","Equipment Descr","Tag Number","Serial Number"|ConvertTo-Html -Property '*' -As Table -Fragment
    $HTMLbody = $body -replace "USER_NAME",$user.'Inactive Emp Name' -replace "USER_ID",$user.'User ID' -replace "EQUIPMENT_LIST", $Equip
    $subject="Equipment for user " + $User.'User ID'
    $mail = $ol.CreateItem(0)
    $mail.To = $User.Manager 
    $mail.Subject = $subject  
    $mail.HTMLBody = $HTMLbody
    $mail.save()
    }

【讨论】:

  • 我更新了问题以解释更多如何使用它。实际上,我已经完成了电子邮件编写部分,我只需要想办法将这些表格放入所说的电子邮件中,这比预期的要困难得多。
  • 这比我以前的优雅多了,谢谢!您是否还可以推荐任何资源来学习更多关于 powershell 的知识,所以下次我至少可以在遇到困难时提出这个问题?
  • 我在学习时并没有真正使用特定的资源(并且随着我继续学习),但我确实/确实使用了很多 Google,并且在早期我参考了嘿,脚本专家!博客很多。
  • 这就是我迄今为止的工作方式(脚本编写人员可能比任何人都教会了我更多)。对于我编写的几个脚本来说,它工作得相当好,但有时我确定应该很简单的答案是不可能通过谷歌找到的,就像在这种情况下一样。
【解决方案2】:

假设您的 csv 有一些列:姓名、姓氏、bla-bla、bla-bla、bla-bla。

$data = import-csv C:\filepath\xx.csv | select name, surname
$data | format-table -groupby (key value)

【讨论】:

  • 谢谢!这是为了取出无关信息并按用户 ID 组织它,但它仍然是同时打印的。有没有办法在每个组更改时分开输出?
  • 对不起,我不关注,您能否在问题中提供示例(只需编辑它)
猜你喜欢
  • 2023-03-13
  • 1970-01-01
  • 2020-08-01
  • 1970-01-01
  • 2021-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-23
相关资源
最近更新 更多