I have CSV1 (as below) where I have to populate the last column from CSV 2 given below..
CSV1
Computer Product Code Country Department LaptopDesktop
-------- ------- ---- ------- ---------- -------------
Com1 EliteDesk 705 HP2190 AU FN
Com2 EliteBook 830 HP1023 AU IT
Com3 EliteBook 830 HP1023 FR FN
Com4 Zbook 15U HP2020 IN FN
Com5 OptiPlex 3010 DL1721 FR FN
CSV2
Product Type Code
------- ---- ----
EliteBook 1030 L HP1020
EliteBook 1040 L HP1021
EliteBook 830 L HP1023
Zbook 15U L HP2020
EliteDesk 800 D HP3035
EliteDesk 705 D HP2190
Thinkpad L480 L LE990
OptiPlex 3010 D DL1721
with below code, I'm unable to update 'LaptopDesktop' column in CSV1 whereas output gets appended with -Append parameter or without that, it just overwrite the whole CSV.....How do I fix this?
{
$SystemData =#()
$Productinfo = Import-Csv "C:\CSV2.csv"
$Mastercsv = Import-Csv "C:\CSV1.csv"
foreach($record in $Mastercsv)
{
$mcode = $($record.code)
$mDLtype = $($record.LaptopDesktop)
$SysType = ($Productinfo | where {$_.code -eq $mcode}).type
if ($SysType -eq $null)
{
$sysType = 'Unknown, due to non-matching code'
}
$AddsysType=New-Object PSCustomObject
Add-Member -InputObject $AddsysType -membertype noteproperty -name "LaptopDesktop" -value $sysType
$SystemData +=$AddsysType
}Return, $SystemData
}
$DeviceType= Update-SystemType
$DeviceType| Export-Csv 'C:\CSV1.csv' -Force -NoTypeInformation
I think the fact you've just opened the file to import then try to export to it again is confusing PowerShell. In any case, it's probably not a good idea to over-write the file in this way as it could lead to corruption. Probably better to write to a separate CSV like this:
function Update-SystemType {
Import-Csv ".\CSV2.csv" | ForEach-Object {$codeHash = #{}}{
$codeHash[$_.Code] = $_
}{}
Import-Csv ".\CSV1.csv" |
ForEach-Object {
$_.LaptopDesktop = $(if($codeHash.ContainsKey($_.Code)){$codeHash[$_.Code].Type}else{"Unknown"})
$_
}
}
Update-SystemType |
Export-Csv '.\CSV3.csv' -Force -NoTypeInformation
If you really want to replace the original afterwards, then you can over-write it like this:
Move-Item -Path .\CSV3.csv -Destination .\CSV1.csv -Force
When posting csv sample data, either use the real comma delimited format -or-
the columnar representation after Import-Csv.
## Q:\TEst\2019\01\17\SO_54236818.ps1
$Mastercsv = Import-Csv ".\CSV1.csv"
$Productinfo = Import-Csv ".\CSV2.csv"
foreach($record in $Mastercsv){
$record.LaptopDesktop = ($Productinfo|Where-Object Code -eq $record.code).Type
}
$Mastercsv | Format-Table -Auto
Sample output
Computer Product Code Country Department LaptopDesktop
-------- ------- ---- ------- ---------- -------------
Com1 EliteDesk 705 HP2190 AU FN D
Com2 EliteBook 830 HP1023 AU IT L
Com3 EliteBook 830 HP1023 FR FN L
Com4 Zbook 15U HP2020 IN FN L
Com5 OptiPlex 3010 DL1721 FR FN D
Com6 unknown na DE IT
Related
I would like to compare values in two columns in file1.csv with file2.csv, then assigned the matching value to a new column in file1.csv.
ATM, this is the working so far. Simpler format would be ideal.
$report = Import-CSV -Path "C:\report.csv" -Encoding UTF8
$reference = Import-CSV -Path "C:\team.csv" -Encoding UTF8
foreach ($team1 in $report){
$matched = $false
foreach ($team2 in $reference){
$obj = "" | select "Type","Setup","Responsible","Team","Main"
if($team1.'Setup' -like "*$($team2.'Main')*"){
$matchCounter++
$matched = $true
$obj.'Type' = $team1.'Type'
$obj.'Setup' = $team1.'Setup'
$obj.'Responsible' = $team1.'Responsible'
$obj.'Team' = $team2.'Team'
$obj | Export-Csv -Path "C:\Output.csv" -Append -NoTypeInformation -Encoding
UTF8
}
}
}
This is what the files like;
file1
type setup responsible
---- ------- -----------
y master fin susan
y sensei kuno peter
y sensei jon peter
y junior jumo
file2
main team
---- -----
master sa1
sensei sr2
jumo st6
desired file3
type setup responsible team
---- ------- ----------- -----
y master fin susan sa1
y sensei kuno peter sr2
y sensei jon peter sr2
y junior jumo st6
What I would like to achieve is column setup and responsible (file1) to be compared to main column (file2) and get its adjacent team. Atm, im not sure how to go about skipping cells in column1 with no reference in file2, but existed in column2. Also, to compare only the first character of setup in file1 with file2.
I guess you you just want to do this:
# $report = Import-CSV -Path "C:\report.csv" -Encoding UTF8
$report = ConvertFrom-Csv #'
type, setup, responsible
y, master fin, susan
y, sensei kuno, peter
y, sensei jon, peter
y, junior, jumo
'#
# $reference = Import-CSV -Path "C:\team.csv" -Encoding UTF8
$reference = ConvertFrom-Csv #'
main, team
master, sa1
sensei, sr2
jumo, st6
'#
foreach ($team1 in $report){
foreach ($team2 in $reference){
if($team1.Setup[0] -eq $team2.Main[0]){
[pscustomobject]#{
Type = $team1.Type
Setup = $team1.Setup
Responsible = $team1.Responsible
Team = $team2.Team
}
}
}
} # |Export-Csv -Path .\Output.csv -NoTypeInformation -Encoding UTF8
Results:
Type Setup Responsible Team
---- ----- ----------- ----
y master fin susan sa1
y sensei kuno peter sr2
y sensei jon peter sr2
y junior jumo st6
Note that the for correctly using the PowerShell Pipeline (and performance reasons), the final (Export-Csv) cmdlet shouldn't reside in your process but actually at the end of the pipeline.
If I import a csv of computer names $computers that looks like this
Host
----
computer5
Computer20
Computer1
and import another csv of data $data that looks like this
Host OS HD Capacity Owner
---- -- -- ------ -----
Computer20 Windows7 C 80 Becky
Computer1 Windows10 C 80 Tom
Computer1 Windows10 D 100 Tom
computer5 Windows8 C 100 sara
computer5 Windows8 D 1000 sara
computer5 Windows8 E 1000 sara
Im trying to do this
foreach ($pc in $computers){
$hostname = $pc.host
foreach ($entry in $data | where {$enty.host -eq $hostname})
{write-host "$entry.Owner"}
}
The foreach statement isn't finding any matches. How can I fix this?
Im trying to do more than just write the owner name but, this is the basic premise
Thanks!
Steve
Replace $enty with $_ inside the Where-Object filter block:
foreach ($entry in $data |Where-Object {$_.host -eq $hostname}){
Write-Host $entry.Owner
}
Here's another way to do it, using an array $computers.host on the left side of the -eq operator:
$computers = 'Host
computer5
Computer20
Computer1' | convertfrom-csv
$data = 'Host,OS,HD,Capacity,Owner
Computer20,Windows7,C,80,Becky
Computer1,Windows10,C,80,Tom
Computer1,Windows10,D,100,Tom
computer5,Windows8,C,100,sara
computer5,Windows8,D,1000,sara
computer5,Windows8,E,1000,sara' | convertfrom-csv
$data | where { $computers.host -eq $_.host } | ft
Host OS HD Capacity Owner
---- -- -- -------- -----
Computer20 Windows7 C 80 Becky
Computer1 Windows10 C 80 Tom
Computer1 Windows10 D 100 Tom
computer5 Windows8 C 100 sara
computer5 Windows8 D 1000 sara
computer5 Windows8 E 1000 sara
Or
$data | where host -in $computers.host
Or
foreach ( $entry in $data | where host -in $computers.host | foreach owner ) {
$entry }
Becky
Tom
Tom
sara
sara
sara
Assuming $entry is spelled correctly, this syntax just happens not to work.
The expression $data | where {$entry.host -eq $hostname} just doesn't make sense by itself. Good question though. You can indeed use a pipeline in the parens after foreach.
foreach ($pc in $computers){
$hostname = $pc.host
foreach ($entry in $data | where {write-host "entry is $entry";
$entry.host -eq $hostname}){
write-host "$entry.Owner"
}
}
entry is
entry is
entry is
entry is
entry is
entry is
entry is
entry is
entry is
entry is
entry is
entry is
entry is
entry is
entry is
entry is
entry is
entry is
could you please help me with powershell script:
In CSV file I need to subtract column B date from column C and write result in column A in format 1 day = 24 hrs and same date = 12 hrs
Sometimes column B can hold future values, in this case column A should contain minus (-)
It should look like this:
120 11/22/2020 11/27/2020
96 11/23/2020 11/27/2020
72 11/24/2020 11/27/2020
48 11/25/2020 11/27/2020
24 11/26/2020 11/27/2020
12 11/27/2020 11/27/2020
-24 11/28/2020 11/27/2020
-48 11/29/2020 11/27/2020
UPD
My script have couple additional steps before subtraction.
I'm taking raw file, TAB delimited, converting it to csv, comparing it with archived files to eliminate duplicates, removing unwanted "SrvDate" column name and replacing it with "TAT\hh" name and then exporting it to file. So the only thing is missing - date comparison and fill hours in "TAT/hh"
Here it is with sample data:
Script:
$in = Import-Csv (Get-ChildItem -Path E:\Test\RI\In\test\In\*.csv).Fullname -Delimiter "`t" | ? "Test Code" -in "Z620","Z630"
$in2 = Import-Csv (Get-ChildItem -Path E:\Test\RI\In\test\Arc\*.csv).Fullname
$pcomp = 'Accession'
$dup = Compare-Object $in $in2 -Property $pcomp -IncludeEqual -ExcludeDifferent -PassThru | Select-Object -ExpandProperty $pcomp
$badhead = $in | Where-Object {$_.$pcomp -notin $dup} | Select-Object *,#{Name='TAT/hh';Expression={$_.'TAT/hh'}} -Exclude 'SrvDate'
$goodhead = $badhead | Select-Object "Accession","TAT/hh","EntryDate","FinalReportDate","Patient First Name","Patient Last Name","DOB","Gender","Race","Ethnicity","Patient Address","Patient City","Patient State","Patient Zip","Patient Phone","Test Code","Test Name","Result","ClientID","Client Name","Phys ID","Phys Name"
if ($goodhead) {$goodhead | Where-Object {$_.$pcomp -notin $dup} | Export-Csv "E:\Test\RI\In\test\Out\Client_PtRecords_$((Get-Date).ToString("yyyyMMdd")).csv" -NoTypeInformation}
Sample data:
Accession SrvDate EntryDate FinalReportDate Patient First Name Patient Last Name DOB Gender Race Ethnicity Patient Address Patient City Patient State Patient Zip Patient Phone Test Code Test Name Result ClientID Client Name Phys ID Phys Name
--------- ------- --------- --------------- ------------------ ----------------- --- ------ ---- --------- --------------- ------------ ------------- ----------- ------------- --------- --------- ------ -------- ----------- -------- ----------
2132900941 NULL 11-24-2020 11-29-2020 MICHELL PENDERGRAS 9/30/1981 F U 35 RUSEVELT ST PRUDENCE RB 2909 (401)516-5642 Z620 Sars-COVID19 Positive 99984 "ASHRAF FARID, M.D." 50845 ATPAV RIGTED
2232900942 NULL 11-25-2020 11-29-2020 MICHEL PENDERGRA 9/30/1982 M U 315 RUSEVELT ST PRUDENCE RB 2909 (401)516-5643 Z620 Sars-COVID19 Positive 99984 "ASHRAF FARID, M.D." 50845 ATPAV RIGTED
2332900943 NULL 11-26-2020 11-29-2020 MICHE PENDERGR 9/30/1983 F U 325 RUSEVELT ST PRUDENCE RB 2909 (401)516-5644 Z620 Sars-COVID19 Positive 99984 "ASHRAF FARID, M.D." 50845 ATPAV RIGTED
2432900944 NULL 11-27-2020 11-29-2020 MICH PENDERG 9/30/1984 M U 335 RUSEVELT ST PRUDENCE RB 2909 (401)516-5645 Z620 Sars-COVID19 Positive 99984 "ASHRAF FARID, M.D." 50845 ATPAV RIGTED
2532900945 NULL 11-28-2020 11-29-2020 ALLISO JEZA 10/13/1977 F U 15 KAUTEEKEE AVE SOUTH PRUDENCE RB 2911 (908)930-9213 Z620 Sars-COVID19 Positive 99984 "ASHRAF FARID, M.D." 50845 ATPAV RIGTED
2632900946 NULL 11-29-2020 11-29-2020 ALLIS JEZ 10/13/1978 M U 151 KAUTEEKEE AVE SOUTH PRUDENCE RB 2911 (908)930-9214 Z620 Sars-COVID19 Positive 99984 "ASHRAF FARID, M.D." 50845 ATPAV RIGTED
2732900947 NULL 11-30-2020 11-29-2020 ALLI JE 10/13/1979 F U 152 KAUTEEKEE AVE SOUTH PRUDENCE RB 2911 (908)930-9215 Z620 Sars-COVID19 Positive 99984 "ASHRAF FARID, M.D." 50845 ATPAV RIGTED
2832900948 NULL 12-1-2020 11-29-2020 ALL J 10/13/1980 M U 153 KAUTEEKEE AVE SOUTH PRUDENCE RB 2911 (908)930-9216 Z620 Sars-COVID19 Positive 99984 "ASHRAF FARID, M.D." 50845 ATPAV RIGTED
UPD
I used Алексей's script and insert it in my, but I've faced problem to combine results from two different calculations.
In my script - I'm getting results with correct headers, searched elements only, exporting only if there are results and without duplicates in $goodhead.
In Алексей's script I'm getting calculations for TurnAround Time in $tat (I've selected calculated column only)
Is there a way to fill in $tat into $goodhead?
Here is my updated code:
$in = Import-Csv (Get-ChildItem -Path E:\Test\RI\In\test\In\*.csv).Fullname -Delimiter "`t" | ? "Test Code" -in "Z620","Z630"
$in2 = Import-Csv (Get-ChildItem -Path E:\Test\RI\In\test\Arc\*.csv).Fullname
$pcomp = 'Accession'
$dup = Compare-Object $in $in2 -Property $pcomp -IncludeEqual -ExcludeDifferent -PassThru | Select-Object -ExpandProperty $pcomp
$badhead = $in | Where-Object {$_.$pcomp -notin $dup} | Select-Object *,#{Name='TAT/hh';Expression={$_.'TAT/hh'}} -Exclude 'SrvDate'
$goodhead = $badhead | Select-Object "Accession","TAT/hh","EntryDate","FinalReportDate","Patient First Name","Patient Last Name","DOB","Gender","Race","Ethnicity","Patient Address","Patient City","Patient State","Patient Zip","Patient Phone","Test Code","Test Name","Result","ClientID","Client Name","Phys ID","Phys Name"
$tatin = $goodhead | Select-Object * | % {
$EntryDate = [datetime]::parseexact($_.EntryDate, 'yyyy-MM-dd', $null)
$FinalReportDate = [datetime]::parseexact($_.FinalReportDate, 'yyyy-MM-dd', $null)
$tatcalc = switch (($FinalReportDate - $EntryDate).TotalDays){
0 {12}
default {$_ * 24}
}
[PSCustomObject]#{
'TAT/hh' = $tatcalc
EntryDate = $EntryDate
FinalReportDate = $FinalReportDate
}
}
$tat = $tatin | Select "TAT/hh"
if ($tat) {$tat | Sort-Object "Result" -Descending | Export-Csv "E:\Test\RI\In\test\Out\Client_PtRecords_$((Get-Date).ToString("yyyyMMdd")).csv" -NoTypeInformation}
Thank you!
P.S. I'm just a beginner with Powershell, trying to learn it on daily tasks.
$in = Import-Csv (Get-ChildItem -Path D:\tmp\alex\Client_PtRecords_20201203.csv).Fullname -Delimiter "`t" | ? "Test Code" -in "Z620","Z630"
$in2 = Import-Csv (Get-ChildItem -Path D:\tmp\alex\arc\Client_PtRecords_20201202.csv).Fullname
$pcomp = 'Accession'
$dup = Compare-Object $in $in2 -Property $pcomp -IncludeEqual -ExcludeDifferent -PassThru | Select-Object -ExpandProperty $pcomp
$badhead = $in | Where-Object {$_.$pcomp -notin $dup} | Select-Object *,#{Name='TAT/hh';Expression={$_.'TAT/hh'}} -Exclude 'SrvDate'
$goodhead = $badhead | Select-Object "Accession", #{name = "TAT/hh"; expression = {switch(([datetime]::parseexact($_.FinalReportDate, 'yyyy-MM-dd', $null)-[datetime]::parseexact($_.EntryDate, 'yyyy-MM-dd', $null)).TotalDays){ 0 {12}; default {$_ * 24}}}},"EntryDate","FinalReportDate","Patient First Name","Patient Last Name","DOB","Gender","Race","Ethnicity","Patient Address","Patient City","Patient State","Patient Zip","Patient Phone","Test Code","Test Name","Result","ClientID","Client Name","Phys ID","Phys Name"
$tatin = $goodhead | Select-Object *
$tat = $tatin | Select "TAT/hh"
if ($tat) {$tat | Sort-Object "Result" -Descending | Export-Csv "D:\tmp\alex\arc\Client_PtRecords_$((Get-Date).ToString("yyyyMMdd")).csv" -NoTypeInformation}
I have seen powershell script which also I have in mind. What I would like to add though is another column which would show the side indicator comparators ("==", "<=", "=>") and be named them as MATCH(if "==") and MISMATCH(if "<=" and "=>").
Any advise on how I would do this?
Here is the link of the script (Credits to Florent Courtay)
How can i reorganise powershell's compare-object output?
$a = Compare-Object (Import-Csv 'C:\temp\f1.csv') (Import-Csv 'C:\temp\f2.csv') -property Header,Value
$a | Group-Object -Property Header | % { New-Object -TypeName psobject -Property #{Header=$_.name;newValue=$_.group[0].Value;oldValue=$_.group[1].Value}}
========================================================================
The output I have in mind:
Header1 Old Value New Value STATUS
------ --------- --------- -----------
String1 Value 1 Value 2 MATCH
String2 Value 3 Value 4 MATCH
String3 NA Value 5 MISMATCH
String4 Value 6 NA MISMATCH
Here's a self-contained solution; simply replace the ConvertFrom-Csv calls with your Import-Csv calls:
# Sample CSV input.
$csv1 = #'
Header,Value
a,1
b,2
c,3
'#
$csv2 = #'
Header,Value
a,1a
b,2
d,4
'#
Compare-Object (ConvertFrom-Csv $csv1) (ConvertFrom-Csv $csv2) -Property Header, Value |
Group-Object Header | Sort-Object Name | ForEach-Object {
$newValIndex, $oldValIndex = ((1, 0), (0, 1))[$_.Group[0].SideIndicator -eq '=>']
[pscustomobject] #{
Header = $_.Name
OldValue = ('NA', $_.Group[$oldValIndex].Value)[$null -ne $_.Group[$oldValIndex].Value]
NewValue = ('NA', $_.Group[$newValIndex].Value)[$null -ne $_.Group[$newValIndex].Value]
Status = ('MISMATCH', 'MATCH')[$_.Group.Count -gt 1]
}
}
The above yields:
Header OldValue NewValue Status
------ -------- -------- ------
a 1 1a MATCH
c 3 NA MISMATCH
d NA 4 MISMATCH
Note:
The assumption is that a given Header column value appears at most once in each input file.
The Sort-Object Name call is needed to sort the output by Header valuesThanks, LotPings.
, because, due to how Compare-Object orders its output (right-side-only items first), the order of groups created by Group-Object would not automatically reflect the 1st CSV's order of header values (d would appear before c).
I'm writing a PowerShell script to read a CSV. I have everything working so far, it's able to find the value from user input (branch number) and finds the values that have "Y" in the available. Please see 2nd picture.
First picture is my CSV file.
This is what I need help with. How would I get the value of the first available CoreID? In this example, FMD354800000. Once I get the first available CoreId, I want to change the Available to N
$Find = $ImportCSV | Select-String -Pattern $GetBranchNum
$Find -match "Y"
New-ItemProperty -path $CoreIP -name "TTable ID" -PropertyType String -Value "Test" -Force
Use Import-Csv to import the CSV:
$csv = Import-Csv 'C:\path\to\your.csv'
Since the file seems to be fixed width you'll need to Trim() fields before checking their value.
$branchNumber = '8000'
$first = $csv | Where-Object {
$_.'Branch Number'.Trim() -eq $branchNumber -and
$_.Available.Trim() -eq 'y'
} | Select-Object -First 1
This filters the CSV for records with the given branch number that have a value Y in the field Available and selects the first matching record.
Then change the value of the Available field of that record:
$first.Available = 'N'
Demonstration:
PS C:\> $csv = Import-Csv 'C:\path\to\sample.csv'
PS C:\> $csv
Branch Number CoreID Available
------------- ------ ---------
8000 FMD354800000 Y
8000 FMD354800001 Y
8000 FMD354800002 N
PS C:\> $first = $csv | Where-Object {
>> $_.'Branch Number'.Trim() -eq '8000' -and
>> $_.Available.Trim() -eq 'y'
>> } | Select-Object -First 1
>>
PS C:\> $first
Branch Number CoreID Available
------------- ------ ---------
8000 FMD354800000 Y
PS C:\> $first.Available = 'N'
PS C:\> $first
Branch Number CoreID Available
------------- ------ ---------
8000 FMD354800000 N
PS C:\> $csv
Branch Number CoreID Available
------------- ------ ---------
8000 FMD354800000 N
8000 FMD354800001 Y
8000 FMD354800002 N
Neither Select-String nor the -match operator are particularly useful in this context, so don't use them.