使用一个文件中的 CSV header 名称创建具有不同 header 名称的新文件
Using CSV header names from one file to create new file with different headers name
大家好!
我完全不熟悉 Powershell 脚本。我的经理指派我为我们将要使用的新系统编写集成脚本。我想利用我们每晚生成的 HR 集成文件中的 headers,并将这些值输入到具有不同 headers 的 CSV 文件中。新系统需要这些特定的 headers.The 搭载原因,是因为我们在 AD 中没有为 UserStatus 定义的属性。该列中的值对新系统至关重要。它将确定是否从系统中添加或删除用户。
这是我当前的脚本:
$dateString = Get-Date -Format yyyyMMdd
$users = Import-Csv -Path "c:\scripts\XXXXXX\ActiveDirectory_$dateString.csv" -Header `
'PreferredName,Last,EmployeeID,Email,UserStatus'
$OutFile = "C:\Scripts\XXXXXX\Test\DeltaFeed_$dateString.csv"
$Outheader = "Funds,Firstname,Lastname,Employeenumber,Email,Action"
Add-Content -Path $OutFile -Value $Outheader
$userFunds = "XXXX"
$action = if ($_.UserStatus -eq 'A')
{'A'}
elseif ($_.UserStatus -eq 'T')
{'D'}
ForEach ($user in $users)
{
$outstring = $userFunds + "," + $_.PreferredName + "," + $_.Last + "," + $_.EmployeeID + "," + $_.Email + "," + $action
Add-Content -Path $OutFile -Value $outstring
}
我 运行 遇到的问题是输出文件有 headers,但每一列中都没有值。我不太确定我在这里做错了什么。我不习惯这种语法。
您的直接问题是您传递的是 单个字符串 ,而不是 header 的 数组(列名称)到 Import-Csv -Header
.
也就是说,而不是:
# WRONG: Single string.
# If you do this, the objects returned will have a SINGLE property
# literally named 'PreferredName,Last,EmployeeID,Email,UserStatus'
-Header 'PreferredName,Last,EmployeeID,Email,UserStatus'
你必须使用:
# OK: ARRAY of names.
-Header PreferredName, Last, EmployeeID, Email, UserStatus
请注意,在 argument 解析模式中(将 argument 传递给 command) ,没有空格的简单数组元素不需要引号;在 expression-parsing 模式下,需要引用,例如当您分配给 变量 ($array = 'PreferredName', 'Last', ...
) 时;有关 PowerShell 的两种解析模式的更多信息,请参阅 this answer。
但是:
这听起来像是将 -Header
与 Import-Csv
一起使用实际上并不是您所需要的,因为您不能仅使用 select 列的子集 。相反,-Header
用于为 缺少 header 行 的输入数据指定列名。 Import-Csv
导入 all columns[1],你可以限制自己只访问那些感兴趣的属性(列) .
正如 Lee_Dailey 所建议的那样,您通常应该使用 objects,使用 Import-Csv
,Select-Object
/ [pscustomobject]
个实例和 Export-Csv
,这大大简化了您的任务。 Plain-text 仅当 object-oriented 处理的性能不足时才需要处理。
在您的情况下,您可以组合 Select-Object
with calculated properties,它可用于 重命名 输入 objects 的属性并提供 动态值:
# Determine in- and output files.
$dateString = Get-Date -Format yyyyMMdd
$inFile = "C:\scripts\XXXXXX\ActiveDirectory_$dateString.csv"
$outFile = "C:\Scripts\XXXXXX\Test\DeltaFeed_$dateString.csv"
# Import, rename properties and add additional ones, then export.
# * -NoTypeInformation is only needed in Windows PowerShell.
# * Adjust the -Encoding argument as needed; Windows PowerShell defaults
# to ASCII(!), PowerShell [Core] v6+ to BOM-less UTF-8.
Import-Csv -Path $inputFile |
Select-Object @{ n='Funds'; e={ 'XXXX' } },
@{ n='Firstname'; e='PreferredName' },
@{ n='Lastname'; e='Last' },
@{ n='Employeenumber'; e='EmployeeID' },
Email, # no renaming required
@{ n='Action'; e = { @{ A='A'; T='D' }[$_.UserStatus] } } |
Export-Csv $outFile -NoTypeInformation -Encoding utf8
[1]如果你使用-Header
并且指定的列名数比数据列数少,那么你可以技术上 return 列的子集,但 (a) 仅 从第一列开始 ,并且 (b) 如前所述,仅当输入数据 具有没有 header 行.
我采取了一些不同的做法。我看到的直接问题是将单个变量传递给 csv。其次,当您真的想使用 Excel 时,我不喜欢使用 CSV。我重写了你的原作来完成你所说的。
#Variable assignation
$dateString = (Get-Date -Format yyyyMMdd)
$userFunds = "XXXX"
$original = “c:\scripts\XXXXXX\ActiveDirectory_$dateString.csv”
$path = “c:\scripts\XXXXXX\Test\DeltaFeed_$dateString.xlsx”
$users = Import-Csv -Path $original
$Excel = New-Object -ComObject excel.application
$Excel.visible = $false #True if you want it to popup before saving.
$workbook = $Excel.workbooks.add()
$excel.cells.item(1,1) = “Funds”
$excel.cells.item(1,2) = “FirstName”
$excel.cells.item(1,3) = “LastName”
$excel.cells.item(1,4) = “Employee Number”
$excel.cells.item(1,5) = “Email”
$excel.cells.item(1,5) = “Action”
$i=2
foreach($user in $users)
{
$action = if ($user.UserStatus -eq 'A')
{'A'}
elseif ($user.UserStatus -eq 'T')
{'D'}
$excel.cells.item($i,1) = $userFunds
$excel.cells.item($i,2) = $user.PreferredName
$excel.cells.item($i,3) = $user.Last
$excel.cells.item($i,4) = $user.EmployeeID
$excel.cells.item($i,5) = $user.Email
$excel.cells.item($i,6) = $user.UserStatus
$excel.cells.item($i,6) = $action
$i++
} #end foreach user
$workbook.saveas($path)
$Excel.Quit()
Remove-Variable -Name excel
[gc]::collect()
[gc]::WaitForPendingFinalizers()
我的解决方案:
$dateString = Get-Date -Format yyyyMMdd
import-csv "C:\scripts\XXXXXX\ActiveDirectory_$dateString.csv" -Header Firstname,Lastname,Employeenumber,Email,Action | %{
if ($_.Action -eq 'T') {$_.Action='D'}
Add-Member -InputObject $_ -NotePropertyName "Funds" -NotePropertyValue "XXXX" -PassThru
} | export-csv "C:\Scripts\XXXXXX\Test\DeltaFeed_$dateString.csv" -NoType
大家好!
我完全不熟悉 Powershell 脚本。我的经理指派我为我们将要使用的新系统编写集成脚本。我想利用我们每晚生成的 HR 集成文件中的 headers,并将这些值输入到具有不同 headers 的 CSV 文件中。新系统需要这些特定的 headers.The 搭载原因,是因为我们在 AD 中没有为 UserStatus 定义的属性。该列中的值对新系统至关重要。它将确定是否从系统中添加或删除用户。
这是我当前的脚本:
$dateString = Get-Date -Format yyyyMMdd
$users = Import-Csv -Path "c:\scripts\XXXXXX\ActiveDirectory_$dateString.csv" -Header `
'PreferredName,Last,EmployeeID,Email,UserStatus'
$OutFile = "C:\Scripts\XXXXXX\Test\DeltaFeed_$dateString.csv"
$Outheader = "Funds,Firstname,Lastname,Employeenumber,Email,Action"
Add-Content -Path $OutFile -Value $Outheader
$userFunds = "XXXX"
$action = if ($_.UserStatus -eq 'A')
{'A'}
elseif ($_.UserStatus -eq 'T')
{'D'}
ForEach ($user in $users)
{
$outstring = $userFunds + "," + $_.PreferredName + "," + $_.Last + "," + $_.EmployeeID + "," + $_.Email + "," + $action
Add-Content -Path $OutFile -Value $outstring
}
我 运行 遇到的问题是输出文件有 headers,但每一列中都没有值。我不太确定我在这里做错了什么。我不习惯这种语法。
您的直接问题是您传递的是 单个字符串 ,而不是 header 的 数组(列名称)到 Import-Csv -Header
.
也就是说,而不是:
# WRONG: Single string.
# If you do this, the objects returned will have a SINGLE property
# literally named 'PreferredName,Last,EmployeeID,Email,UserStatus'
-Header 'PreferredName,Last,EmployeeID,Email,UserStatus'
你必须使用:
# OK: ARRAY of names.
-Header PreferredName, Last, EmployeeID, Email, UserStatus
请注意,在 argument 解析模式中(将 argument 传递给 command) ,没有空格的简单数组元素不需要引号;在 expression-parsing 模式下,需要引用,例如当您分配给 变量 ($array = 'PreferredName', 'Last', ...
) 时;有关 PowerShell 的两种解析模式的更多信息,请参阅 this answer。
但是:
这听起来像是将
-Header
与Import-Csv
一起使用实际上并不是您所需要的,因为您不能仅使用 select 列的子集 。相反,-Header
用于为 缺少 header 行 的输入数据指定列名。Import-Csv
导入 all columns[1],你可以限制自己只访问那些感兴趣的属性(列) .正如 Lee_Dailey 所建议的那样,您通常应该使用 objects,使用
Import-Csv
,Select-Object
/[pscustomobject]
个实例和Export-Csv
,这大大简化了您的任务。 Plain-text 仅当 object-oriented 处理的性能不足时才需要处理。
在您的情况下,您可以组合 Select-Object
with calculated properties,它可用于 重命名 输入 objects 的属性并提供 动态值:
# Determine in- and output files.
$dateString = Get-Date -Format yyyyMMdd
$inFile = "C:\scripts\XXXXXX\ActiveDirectory_$dateString.csv"
$outFile = "C:\Scripts\XXXXXX\Test\DeltaFeed_$dateString.csv"
# Import, rename properties and add additional ones, then export.
# * -NoTypeInformation is only needed in Windows PowerShell.
# * Adjust the -Encoding argument as needed; Windows PowerShell defaults
# to ASCII(!), PowerShell [Core] v6+ to BOM-less UTF-8.
Import-Csv -Path $inputFile |
Select-Object @{ n='Funds'; e={ 'XXXX' } },
@{ n='Firstname'; e='PreferredName' },
@{ n='Lastname'; e='Last' },
@{ n='Employeenumber'; e='EmployeeID' },
Email, # no renaming required
@{ n='Action'; e = { @{ A='A'; T='D' }[$_.UserStatus] } } |
Export-Csv $outFile -NoTypeInformation -Encoding utf8
[1]如果你使用-Header
并且指定的列名数比数据列数少,那么你可以技术上 return 列的子集,但 (a) 仅 从第一列开始 ,并且 (b) 如前所述,仅当输入数据 具有没有 header 行.
我采取了一些不同的做法。我看到的直接问题是将单个变量传递给 csv。其次,当您真的想使用 Excel 时,我不喜欢使用 CSV。我重写了你的原作来完成你所说的。
#Variable assignation
$dateString = (Get-Date -Format yyyyMMdd)
$userFunds = "XXXX"
$original = “c:\scripts\XXXXXX\ActiveDirectory_$dateString.csv”
$path = “c:\scripts\XXXXXX\Test\DeltaFeed_$dateString.xlsx”
$users = Import-Csv -Path $original
$Excel = New-Object -ComObject excel.application
$Excel.visible = $false #True if you want it to popup before saving.
$workbook = $Excel.workbooks.add()
$excel.cells.item(1,1) = “Funds”
$excel.cells.item(1,2) = “FirstName”
$excel.cells.item(1,3) = “LastName”
$excel.cells.item(1,4) = “Employee Number”
$excel.cells.item(1,5) = “Email”
$excel.cells.item(1,5) = “Action”
$i=2
foreach($user in $users)
{
$action = if ($user.UserStatus -eq 'A')
{'A'}
elseif ($user.UserStatus -eq 'T')
{'D'}
$excel.cells.item($i,1) = $userFunds
$excel.cells.item($i,2) = $user.PreferredName
$excel.cells.item($i,3) = $user.Last
$excel.cells.item($i,4) = $user.EmployeeID
$excel.cells.item($i,5) = $user.Email
$excel.cells.item($i,6) = $user.UserStatus
$excel.cells.item($i,6) = $action
$i++
} #end foreach user
$workbook.saveas($path)
$Excel.Quit()
Remove-Variable -Name excel
[gc]::collect()
[gc]::WaitForPendingFinalizers()
我的解决方案:
$dateString = Get-Date -Format yyyyMMdd
import-csv "C:\scripts\XXXXXX\ActiveDirectory_$dateString.csv" -Header Firstname,Lastname,Employeenumber,Email,Action | %{
if ($_.Action -eq 'T') {$_.Action='D'}
Add-Member -InputObject $_ -NotePropertyName "Funds" -NotePropertyValue "XXXX" -PassThru
} | export-csv "C:\Scripts\XXXXXX\Test\DeltaFeed_$dateString.csv" -NoType