How to fix broken lines records of a file using PowerShell? - powershell

In my csv file I'm getting data in incorrect format for a few rows, sometimes a line is broken into two lines as shown in below table. For EmpId 2, line is broken into two lines. How can I find such records and merge them into one line in correct format to fix the issue for such records using PowerShell. Expected output is shown in below table.
Input File data:
EmpId,EmpName,EmpLocation
1,"Jack","Austin"
2,"Pet
er","NYC"
3,"Raj","Delhi"
Expected Output:
EmpId,EmpName,EmpLocation
1,"Jack","Austin"
2,"Peter","NYC"
3,"Raj","Delhi"

My instinct was to do something similar to Karthick's answer, however I first took a look at the output of Import-Csv. Surprisingly it puts the line break in the individual property where it was found like:
Import-Csv C:\temp\Broken.csv | fl
EmpId : 1
EmpName : Jack
EmpLocation : Austin
EmpId : 2
EmpName : Pet
er
EmpLocation : NYC
EmpId : 3
EmpName : Raj
EmpLocation : Delhi
Notice "peter" is broken across 2 lines.
So I saw some potential to bring the objects in and modify the underlying property values instead of trying to fix up the string data. I cooked up the below:
$CSVData = Import-Csv C:\temp\Broken.csv
$CSVData |
ForEach-Object{
ForEach( $Property in $_.PSObject.Properties.Name )
{
$_.($Property) = $_.($Property) -replace "(`r|`n)"
}
}
$CSVData
# If you want to re-export:
$CSVData | Export-Csv -Path c:\temp\Fixed.csv -NoTypeInformation
This code should work regardless of which field has the line break. Give it a shot and let me know. Thanks!

You can try the below. This worked for me. I assumed the first line is the header.
$filepath = "D:\file.csv"
[string[]]$data = Get-Content $filepath
$data_Final = New-Object System.Collections.ArrayList
for($i = $j = 0; $i -lt $data.Count; $(if($i -eq $j){$i++}else{$i=$j+1}), ($j=$i)) {
While ( ($data[$i] -split ",").Count -ne 3 ) {
$j = $j+1
# Concatenate the target line ($i) with successive line(s) ($j) until the elements Count to 3
$data[$i] = $data[$i] + $data[$j]
}
$data_Final.Add($data[$i]) | Out-Null
}
$inputData = $data_Final | ConvertFrom-Csv
# Or, if you want to fix the csv uncomment the below
# $data_Final | ConvertFrom-Csv | Export-Csv $filepath -NoTypeInformation

Related

Split Columns with delimiter and export to csv

I have a csv file that contains data in the below format:
Name Codes
------- ---------
John AJFKC,EFUY
Ben EFOID, EIUF
Alex OIPORE, OUOIJE
I would like to get the above in the below format and output it into a new csv file as below:
Name Codes
------- ---------
John AJFKC
John EFUY
Ben EFOID
Ben EIUF
Alex OIPORE
Alex OUOIJE
You can do the following if there will always be 2 codes per name:
Import-Csv file.csv | Foreach-Object {
$codes = ($_.Codes -split ',').Trim()
[pscustomobject]#{Name = $_.Name; Codes = $codes[0]}
[pscustomobject]#{Name = $_.Name; Codes = $codes[1]}
}
If the number of codes per name is unknown, you can do the following:
Import-Csv file.csv | Foreach-Object {
$codes = ($_.Codes -split ',').Trim()
foreach ($code in $codes) {
[pscustomobject]#{Name = $_.Name; Codes = $code}
}
}
If this is how this file really looks, it's not a Csv file. It's just a text file based copying and using what you posted. It's left-justified, vs columns, here the staggered look of it. The file has 5 spaces for that name column between it and that left justified Codes column with a code array.
So, though it looks like a table/tabular format, it's not really that. As in an import that name column would include the first of the code strings, thus cause some issues with your desired output. So, that text file would need to be manipulated a bit more, or who or whatever provides you the file, should make is a legitimate CSV.
So, here's my take on the assumptions in the aforementioned.
(Get-Content -Path 'D:\Temp\UserRecord.csv') -replace ', ',',' |
Select -Skip 2 |
ForEach {
$Name = (($PSItem) -split '\s+')[0]
($PSItem -split '\s+')[1] -split ',' |
ForEach {
[PSCustomObject]#{
Name = $Name
Codes = $PSItem
}
}
}
# Results
<#
Name Codes
---- -----
John AJFKC
John EFUY
Ben EFOID
Ben EIUF
Alex OIPORE
Alex OUOIJE
#>
try this:
Import-Csv "c:\temp\test.csv" -Delimiter "`t" | %{
$Name=$_.Name
$_.Codes -split "," | %{ [pscustomobject]#{Name=$Name;Code=$_.Trim()}}
}

How to convert text files in a folder into a CSV file

I am trying to write a script to take a bunch of text files in a folder (which are all in the same format) and output them to a csv file. Each file has the same "header" information. I have been able to get information in a more easily usable format (removing the first and last lines, which aren't needed), but am having some trouble after that.
Here is the beginning of the text file, though there will be more than just these 7 lines, there will be a total of 36 lines per file:
TYPE VOID
DOB 20200131
DATE 20200131
TIME 21:19:42
TERMINAL 3
ORGTERM 2
EMPLOYEE 1234 John Doe
And here is what I have so far, though I know that it doesn't work:
$currentdir = '.\'
$results = #()
$outputfilename = 'data.csv'
foreach ($req in Get-ChildItem($currentdir)) {
(Get-Content $req)[1..((Get-Content $req).count - 2)] |
ForEach-Object {
$header = $_[0] -split '`t'
$data = $_[1] -split '`t'
$results = $header, $data
}
}
The final product would look something like this:
A B C D E F G
1 TYPE DOB DATE TIME TERMINAL ORGTERM EMPLOYEE
2 VOID 20200131 20200131 21:19:42 3 2 1234 John Doe
3 AUTHORIZE 20200131 20200131 23:29:22 2 4678 Jane Doe
Full sample of VOID file:
BEGIN
TYPE VOID
DOB 20200131
DATE 20200131
TIME 21:19:42
TERMINAL 3
ORGTERM 2
EMPLOYEE 1234 Jane Doe
TABLE TBL 101
CHECK 20030
PAYMENT 20029
AUTHAMT 20.68
BATCHAMT 20.68
CARDTYPE MASTERCARD
CARDMASK XXXXXXXXXXXXXXXXX
{XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}
EXP 0423
REF 482
STANDALONE YES
PINDEX 1
APPROVEAMT 20.68
LOGTIME 21:07:01
FOHFEATS 10000000000000000000000000000000
TERMCAPS 00000000000000000000000000000000
FOHVERSION 15.1.34.2.97
ACTIONCODE 000
LASTSEND 1580585993
ORIGDATE 20200131
ORIGTIME 21:02:11
ORIGTYPE AUTHORIZE
ORIGREF 482
ORGREFTIME 21:02:11
TENDER_NUM 12
CRCY 840
VPD Sequence #: 107
REVID 2
REVNAME 712 Bar
END
Sample AUTHORIZE file:
BEGIN
TYPE AUTHORIZE
DOB 20200131
DATE 20200131
TIME 23:29:22
TERMINAL 2
EMPLOYEE 1234 Jane Doe
TABLE Table 121
CHECK 20045
PAYMENT 20038
AUTHAMT 72.42
BATCHAMT 72.42
CARDTYPE VISA
CARDMASK XXXXXXXXXXXXXXXX
{XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}
EXP 0124
REF 485900
STANDALONE YES
PINDEX 1
LOGTIME 23:29:22
FOHFEATS 10000000000000000000000000000000
TERMCAPS 00000000000000000000000000000000
FOHVERSION 15.1.34.2.97
LASTSEND 1580586235
TENDER_NUM 13
CRCY 840
REVID 1
REVNAME 712 Restaurant
COMMERROR TRUE
END
Sample adjust file:
BEGIN
TYPE ADJUST
DOB 20200131
DATE 20200131
TIME 22:18:27
TERMINAL 8
ORGTERM 8
EMPLOYEE 789 Judy Garland
TABLE BAR GUEST
CHECK 80161
PAYMENT 80036
BATCHAMT 30.43
BATCHTIP 6
CARDTYPE MASTERCARD
CARDMASK XXXXXXXXXXXX8699
{XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}
EXP 0323
REF 1504602
STANDALONE YES
PINDEX 1
LOGTIME 22:18:27
FOHFEATS 10000000000000000000000000000000
TERMCAPS 00000000000000000000000000000000
FOHVERSION 15.1.34.2.97
LASTSEND 1580638928
TENDER_NUM 12
CRCY 840
REVID 4
REVNAME 712 Second Bar
END
here's one way to merge those text files into a CSV. it presumes the files are in a specific dir and can be loaded by matching the names OR by simply grabbing all the files.
what it does ...
sets the source dir
sets the file filter
grabs all the matching files
iterates thru the file list
loads each file into a $Var
uses the way that PoSh handles a collection on the LEFT side of a match
that gives you the matching item, not the usual [bool].
builds a PSCustomObject
it does that by matching the line with the target word, getting the 1st item in the returned array, replaces the unwanted part of the line with nothing, and finally assigns that value to the desired property.
this is rather inefficient, but i can't think of a better way. [blush]
sends the PSCO out to the $Results collection
shows what is in $Results on the screen
exports $Results to a CSV file
here's the code ...
$SourceDir = $env:TEMP
$Filter = 'harlan_*.txt'
$FileList = Get-ChildItem -LiteralPath $SourceDir -Filter $Filter -File
$Results = foreach ($FL_Item in $FileList)
{
$Lines = Get-Content -LiteralPath $FL_Item.FullName
[PSCustomObject]#{
Type = ($Lines -match '^type')[0] -replace '^type\s{1,}'
DOB = ($Lines -match '^dob')[0] -replace '^dob\s{1,}'
Date = ($Lines -match '^date')[0] -replace '^date\s{1,}'
Time = ($Lines -match '^time')[0] -replace '^time\s{1,}'
Terminal = ($Lines -match '^terminal')[0] -replace '^terminal\s{1,}'
OrgTerm = ($Lines -match '^orgterm')[0] -replace '^orgterm\s{1,}'
Employee = ($Lines -match '^employee')[0] -replace '^employee\s{1,}'
}
}
# show on screen
$Results
# save to CSV
$Results |
Export-Csv -LiteralPath "$SourceDir\Harlan_-_MergedFiles.csv" -NoTypeInformation
display on screen ...
Type : ADJUST
DOB : 20200131
Date : 20200131
Time : 22:18:27
Terminal : 8
OrgTerm : 8
Employee : 789 Judy Garland
Type : AUTHORIZE
DOB : 20200131
Date : 20200131
Time : 23:29:22
Terminal : 2
OrgTerm :
Employee : 1234 Jane Doe
Type : VOID
DOB : 20200131
Date : 20200131
Time : 21:19:42
Terminal : 3
OrgTerm : 2
Employee : 1234 Jane Doe
content of the csv file ...
"Type","DOB","Date","Time","Terminal","OrgTerm","Employee"
"ADJUST","20200131","20200131","22:18:27","8","8","789 Judy Garland"
"AUTHORIZE","20200131","20200131","23:29:22","2","","1234 Jane Doe"
"VOID","20200131","20200131","21:19:42","3","2","1234 Jane Doe"
To capture all fields in the files without hardcoding the headers and combine them into a CSV file, the below code should do it.
Snag is that there is one line in each file that does not have a 'Header', it is just a string {XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}.
I'm guessing that should be the Card Number, so I'm manually inserting the header CARDNUMBER there. If this is something else, please change that in the code.
$files = Get-ChildItem -Path 'D:\Test' -File
$result = foreach($file in $files) {
$obj = [PsCustomObject]#{}
Get-Content -Path $file.FullName | Where-Object { $_ -notmatch '^(BEGIN|END)$' } | ForEach-Object {
# There is a line without 'header' name. Is this the card number?
if ($_ -like '{*}') {
$name = 'CARDNUMBER' # <-- add your own preferred header name here
$value = $_
}
else {
$name,$value = $_ -split '\s+', 2
}
$obj | Add-Member -MemberType NoteProperty -Name $name -Value $value
}
# output the object for this file to be colected in the $result variable
$obj
}
# output on screen
$result
#output to CSV file
$result | Export-Csv -Path 'D:\output.csv' -NoTypeInformation
You need to set the paths for Get-ChildItem and Export-CSV to match your own situation of course
If I'm reading this correctly you have some files each has a single record of data delimited between the aptly positions words "BEGIN" & "END" You want each file to be translated into a single CSV file?
I think I've cooked up something worth while. Though I'm sure it's not perfect.
$Select = 'TYPE','DOB','DATE','TIME','TERMINAL','ORGTERM','EMPLOYEE'
ForEach( $InputFile in (Get-ChildItem $CurrentDirectory) )
{
$OutputFile = $InputFile.BaseName + '.csv'
$Table = Get-Content $InputFile
$TempHash = [Ordered]#{}
ForEach( $Column in $Table )
{
If( $Column -notmatch '(^BEGIN$|^END$)' )
{
$TempArr = $Column.Split( ' ', 2, [System.StringSplitOptions]::RemoveEmptyEntries ) | ForEach{$_.Trim()}
If( $Select -contains $TempArr[0] )
{
$TempHash.Add($TempArr[0], $TempArr[1] )
}
}
}
#Now $TempHash should have enough to create the object and export to CSV
[PSCustomObject]$TempHash | Export-Csv -Path $OutputFile -NoTypeInformation
}
A few points:
I'm ignoring the lines BEGIN & END
I'm manipulating each line thereafter into an array, which for the
most part should be 2 elements.
If the first element [0] is in the collection of fileds your looking
for I'll add as a key/value pair to the hash. Otherwise do nothing.
After processing the lines Convert the object to a PSCustomObject and
export to a CSV file.
I only tested it on a single file I created from your question. I wrapped up the outer loop just as pseudo code.
This works, but the output looks a little choppy, like numbers being strings and such. That said, as a rev one I think we've got something to work with.
If misread your comment, and you want a single output CSV file the adjustment is just to declare the filename before the loop and use the append param on the Export-CSV cmdlet. See below, though I didn't test it any further:
$OutputFile = 'YourOutput.csv'
$Select = 'TYPE','DOB','DATE','TIME','TERMINAL','ORGTERM','EMPLOYEE'
ForEach( $InputFile in (Get-ChildItem $CurrentDirectory) )
{
$Table = Get-Content $InputFile
$TempHash = [Ordered]#{}
ForEach( $Column in $Table )
{
If( $Column -notmatch '(^BEGIN$|^END$)' )
{
$TempArr = $Column.Split( ' ', 2, [System.StringSplitOptions]::RemoveEmptyEntries ) | ForEach{$_.Trim()}
If( $Select -contains $TempArr[0] )
{
$TempHash.Add($TempArr[0], $TempArr[1] )
}
}
}
#Now $TempHash should have enough to create the object and export to CSV
[PSCustomObject]$TempHash | Export-Csv -Path $OutputFile -NoTypeInformation -Append
}
Sorry about the variable names, that could obviously use a refactor...
Let me know what you think.

Edit one .CSV using Information from Another

I have two .csv files, one with a listing of employee ID's and a department identification number, and another with a listing of all equipment registered to them. The two files share the employee ID field, and I would like to take the department number from the first file and add it to each piece of the corresponding employee's equipment in the second file (or possibly output a third file with the joined information if that is the most expedient method). So far I have pulled the information I need from the first file and am storing it in a hash table, which I believe I should be able to use to compare to the other file, but I'm not sure exactly how to go about that. The other questions I have found on the site that may be related seem to be exclusively about checking for duplicates/changes between the two files. Any help would be much appreciated. Here is the code I have for creating the hashtable:
Import-Csv "filepath\filename.csv"|ForEach-Object -Begin{
$ids = #{}
} -Process {
$ids.Add($_.UserID,$_.'Cost Center')}
Edit:
Here is a sample of data:
First CSV:
UserID | Legal Name | Department
---------------------------------
XXX123| Namey Mcnamera | 1234
XXX321| Chet Manley | 4321
XXX000| Ron Burgundy | 9999
Second CSV:
Barcode | User ID | Department
--------------------------------
000000000000 | xxx123 | 0000
111111111111 | xxx123 | 0000
222222222222 | xxx123 | 0000
333333333333 | xxx321 | 0000
444444444444 | xxx321 | 0000
555555555555 | xxx000 | 0000
The second csv also has several more columns of data, but these three are the only ones I care about.
Edit 2:
Using this code from #wOxxOm (edited to add -force parameters as was receiving an error when attempting to write to department column due to an entry already existing):
$csv1 = Import-Csv "filename.csv"
$csv2 = Import-CSV "filename.csv"
$indexKey = 'UserID'
$index1 = #{}; foreach($row in $csv1){$index1[$row.$indexKey] = $row.'department'}
$copyfield = 'department'
foreach($row in $csv2){
if ($matched = $index1[$row.'User ID']){
Add-Member #{$copyField = $matched.$copyfield} -InputObject $row -Force
}
}
export-csv 'filepath.csv' -NoTypeInformation -Encoding UTF8 -InputObject $csv2 -Force
outputs the following information:
Count Length LongLength Rank SyncRoot IsReadOnly IsFixedSize IsSynchronized
48 48 48 1 System.Object[] FALSE TRUE FALSE
EDIT 3:
Got everything worked out with help from #Ross Lyons. Working code is as follows:
#First Spreadsheet
$users = Import-Csv "filepath.csv"
#Asset Listing
$assets = Import-Csv "filepath.csv"
[System.Array]$data = ""
#iterating through each row in first spreadsheet
foreach ($user in $users) {
#iterating through each row in the second spreadsheet
foreach ($asset in $assets) {
#compare user ID's in each spreadsheet
if ($user.UserID -eq $asset.'User ID'){
#if it matches up, copy the department data, user ID and barcode from appropriate spreadsheets
$data += $user.UserID + "," + $user."Department" + "," + $asset."Barcode" + ","
}
}
}
$data | Format-Table | Out-File "exportedData.csv" -encoding ascii -Force
Ok first, be gentle please, I'm still learning myself! Let me know if the following works or if anything is glaringly obviously wrong...
#this is your first spreadhseet with usernames & department numbers
$users = Import-Csv "spreadsheet1.csv"
#this is your second spreadsheet with equipment info & user ID's, but no department numbers
$assets = Import-Csv "spreadsheet2.csv"
#set a variable for your export data to null, so we can use it later
$export = ""
#iterating through each row in first spreadsheet
foreach ($user in $users) {
#iterating through each row in the second spreadsheet
foreach ($asset in $assets) {
#compare user ID's in each spreadsheet
if ($user.UserID -like $asset.'User ID')
#if it matches up, copy the department data, user ID and barcode from appropriate spreadsheets
$data = "$user.UserID" + "," + "$user.Department" + "," + "$asset.barcode" + "," + "~"
#splits the data based on the "~" that we stuck in at the end of the string
$export = $data -split "~" | Out-File "exportedData.csv" -Encoding ascii
}
}
Let me know what you think. Yes, I know this is probably not the best or most efficient way of doing it, but I think it will get the job done.
If this doesn't work, let me know and I'll have another crack at it.
The hashtable key should be the common field, its value should be the entire row which you can simply access later as $hashtable[$key]:
$csv1 = Import-Csv 'r:\1.csv'
$csv2 = Import-Csv 'r:\2.csv'
# build the index
$indexKey = 'employee ID'
$index1 = #{}; foreach ($row in $csv1) { $index1[$row.$indexKey] = $row }
# use the index
$copyField = 'department number'
foreach ($row in $csv2) {
if ($matched = $index1[$row.$indexKey]) {
Add-Member #{$copyField = $matched.$copyField} -InputObject $row
}
}
Export-Csv 'r:\merged.csv' -NoTypeInformation -Encoding UTF8 -InputObject $csv2
The code doesn't use pipelines for overall speedup.

Loop through csv compare content with an array and then add content to csv

I don't know how to append a string to CSV. What am I doing:
I have two csv files. One with a list of host-names and id's and another one with a list of host-names and some numbers.
Example file 1:
Hostname | ID
IWBW140004 | 3673234
IWBW130023 | 2335934
IWBW120065 | 1350213
Example file 2:
ServiceCode | Hostname | ID
4 | IWBW120065 |
4 | IWBW140004 |
4 | IWBW130023 |
Now I read the content of file 1 in a two dimensional array:
$pcMatrix = #(,#())
Import-Csv $outputFile |ForEach-Object {
foreach($property in $_.PSObject.Properties){
$pcMatrix += ,($property.Value.Split(";")[1],$property.Value.Split(";")[2])
}
}
Then I read the content of file 2 and compare it with my array:
Import-Csv $Group".csv" | ForEach-Object {
foreach($property in $_.PSObject.Properties){
for($i = 0; $i -lt $pcMatrix.Length; $i++){
if($pcMatrix[$i][0] -eq $property.Value.Split('"')[1]){
#Add-Content here
}
}
}
}
What do I need to do, to append $pcMatrix[$i][1] to the active column in file 2 in the row ID?
Thanks for your suggestions.
Yanick
It seems like you are over-complicating this task.
If I understand you correctly, you want to populate the ID column in file two, with the ID that corresponds to the correct hostname from file 1. The easiest way to do that, is to fill all the values from the first file into a HashTable and use that to lookup the ID for each row in the second file:
# Read the first file and populate the HashTable:
$File1 = Import-Csv .\file1.txt -Delimiter "|"
$LookupTable = #{}
$File1 |ForEach-Object {
$LookupTable[$_.Hostname] = $_.ID
}
# Now read the second file and update the ID values:
$File2 = Import-Csv .\file2.txt -Delimiter "|"
$File2 |ForEach-Object {
$_.ID = $LookupTable[$_.Hostname]
}
# Then write the updated rows back to a new CSV file:
$File2 | Export-CSV -Path .\file3.txt -NoTypeInformation -Delimiter "|"

compare columns in two csv files

With all of the examples out there you would think I could have found my solution. :-)
Anyway, I have two csv files; one with two columns, one with 4. I need to compare one column from each one using powershell. I thought I had it figured out but when I did a compare of my results, it comes back as false when I know it should be true. Here's what I have so far:
$newemp = Import-Csv -Path "C:\Temp\newemp.csv" -Header login_id, lastname, firstname, other | Select-Object "login_id"
$ps = Import-Csv -Path "C:\Temp\Emplid_LoginID.csv" | Select-Object "login id"
If ($newemp -eq $ps)
{
write-host "IDs match" -forgroundcolor green
}
Else
{
write-host "Not all IDs match" -backgroundcolor yellow -foregroundcolor black
}
I had to specifiy headers for the first file because it doesn't have any. What's weird is that I can call each variable to see what it holds and they end up with the same info but for some reason still comes up as false. This occurs even if there is only one row (not counting the header row).
I started to parse them as arrays but wasn't quite sure that was the right thing. What's important is that I compare row1 of the first file with with row1 of the second file. I can't just do a simple -match or -contains.
EDIT: One annoying thing is that the variables seem to hold the header row as well. When I call each one, the header is shown. But if I call both variables, I only see one header but two rows.
I just added the following check but getting the same results (False for everything):
$results = Compare-Object -ReferenceObject $newemp -DifferenceObject $ps -PassThru | ForEach-Object { $_.InputObject }
Using latkin's answer from here I think this would give you the result set you're looking for. As per latkin's comment, the property comparison is redundant for your purposes but I left it in as it's good to know. Additionally the header is specified even for the csv with headers to prevent the header row being included in the comparison.
$newemp = Import-Csv -Path "C:\Temp\_sotemp\Book1.csv" -Header loginid |
Select-Object "loginid"
$ps = Import-Csv -Path "C:\Temp\_sotemp\Book2.csv" -Header loginid |
Select-Object "loginid"
#get list of (imported) CSV properties
$props1 = $newemp | gm -MemberType NoteProperty | select -expand Name | sort
$props2 = $ps | gm -MemberType NoteProperty | select -expand Name | sort
#first check that properties match
#omit this step if you know for sure they will be
if(Compare-Object $props1 $props2){
throw "Properties are not the same! [$props1] [$props2]"
}
#pass properties list to Compare-Object
else{
Compare-Object $newemp $ps -Property $props1
}
In the second line, I see there a space "login id" and the first line doesn't have it. Could that be an issue. Try having the same name for the headers in the .csv files itself. And it works for without providing header or select statements. Below is my experiment based upon your input.
emp.csv
loginid firstname lastname
------------------------------
abc123 John patel
zxy321 Kohn smith
sdf120 Maun scott
tiy123 Dham rye
k2340 Naam mason
lk10j5 Shaan kelso
303sk Doug smith
empids.csv
loginid
-------
abc123
zxy321
sdf120
tiy123
PS C:\>$newemp = Import-csv C:\scripts\emp.csv
PS C:\>$ps = Import-CSV C:\scripts\empids.csv
PS C:\>$results = Compare-Object -ReferenceObject $newemp -DifferenceObject $ps | foreach { $_.InputObject}
Shows the difference objects that are not in $ps
loginid firstname lastname SideIndicator
------- --------- -------- -------------
k2340 Naam mason <=
lk10j5 Shaan kelso <=
303sk Doug smith <=
I am not sure if this is what you are looking for but i have used the PowerShell to do some CSV formatting for myself.
$test = Import-Csv .\Desktop\Vmtools-compare.csv
foreach ($i in $test) {
foreach ($n in $i.name) {
foreach ($m in $test) {
$check = "yes"
if ($n -eq $m.prod) {
$check = "no"
break
}
}
if ($check -ne "no") {$n}
}
}
this is how my excel csv file looks like:
prod name
1 3
2 5
3 8
4 2
5 0
and script outputs this:
8
0
so basically script takes each number under Name column and then checks it against prod column. If the number is there then it won't display else it will display that number.
I have also done it the opposite way:
$test = Import-Csv c:\test.csv
foreach ($i in $test) {
foreach ($n in $i.name) {
foreach ($m in $test) {
$check = "yes"
if ($n -eq $m.prod) {echo $n}
}
}
}
this is how my excel csv looks like:
prod name
1 3
2 5
3 8
4 2
5 0
and script outputs this:
3
5
2
so script shows the matching entries only.
You can play around with the code to look at different columns.