Merging two CSV files with Powershell - powershell

I have two CSV files.Columns names are like below example
CSV1
SAMAccountName mail
JohnS johns#example.com
CSV2
GivenName Surname DisplayName Department Title Mail MobilePhone Manager
What I've wanted to do is to compare the CSV1 with CSV2 and match the mail column in CSV2 file with SAMAccountName Column in CSV1 and export a new CSV which gives the below output
CSV3(merged.csv) as in script
GivenName Surname DisplayName Department Title Mail MobilePhone Manager SAMAccountName
I tried the below powershell script which i found in stack overflow site posted sometime back and i never got the values from the SAMAccountName column of CSV1.All other column names are coming up without any issue but SAMAccountName column is blank.I'm not a powershell script expert need some help here.Below is the example script i used.
$csv1 = Import-Csv -Path C:\TEMP\CSV1.csv
$csv2 = Import-Csv -Path C:\temp\CSV2.csv
ForEach($Record in $csv2){
$MatchedValue = (Compare-Object $csv1 $Record -Property "SAMAccountName" -IncludeEqual -ExcludeDifferent -PassThru).value
$Record = Add-Member -InputObject $Record -Type NoteProperty -Name "SAMAccountName" -Value $MatchedValue
}
$csv2|Export-Csv 'C:\temp\merged.csv' -NoTypeInformation

This is very common, You can do this quite easily using:
$csv1 = Import-Csv -Path 'C:\temp\CSV1.csv'
$csv2 = Import-Csv -Path 'C:\temp\CSV2.csv'
$csv3 = foreach ($record in $csv2) {
$matchingRecord = $csv1 | Where-Object { $_.mail -eq $record.mail }
# if your goal is to ONLY export records with a matching email address,
# uncomment the if ($matchingRecord) condition
#if ($matchingRecord) {
$record | Select-Object *, #{Name = 'SamAccountName'; Expression = {$matchingRecord.SamAccountName}}
#}
}
$csv3 | Export-Csv -Path 'C:\temp\merged.csv' -NoTypeInformation

Related

PowerShell - Import CSV, Read Column Value, Use Column Value to Query AD, Add New columns with Queried AD Values

I have a CSV file with the following header names:
Name, Date, Owner
I want to use PowerShell to
Import the File1.csv that contains header values "Name", "Date", "Owner", "Extra"
Read the "Owner" column (contains samaccountnames) and use it to query AD to find the "department, division" attributes associated with each user.
Create two new columns named "Department" and "Division" then export the CSV into a new CSV (file2.csv)
Here's the code I have so far:
$file1 = Import-csv -path "C:\temp\File1.csv"
ForEach ($record in $file1) {
$getAttributes = Get-ADUser -Filter $record.Owner | Select-Object division,department
$record | Add-Member -MemberType NoteProperty -Name "Division" -Value $getAttributes.Division
$record | Add-Member -MemberType NoteProperty -Name "Department" -Value $getAttributes.Department
$record | Export-Csv -Path C:\temp\file2.csv -Encoding UTF8 -NoTypeInformation -Append
}
I have tried different variations and nothing has worked for me so far. Any assistance would be appreciated!
The two main issues with your code are:
-Filter $record.Owner is not a valid syntax for the ActiveDirectory Filter.
Get-ADUser does not return an object with the attributes Department and Division unless you specifically ask to query them (-Properties Department, Division).
Import-csv -Path "C:\temp\File1.csv" | ForEach-Object {
$usr = Get-ADUser -LDAPFilter "(samaccountname=$($_.Owner))" -Properties Department, Division
if(-not $usr) {
# if the user could not be found skip it
Write-Warning "'$($_.Owner)' could not be found..."
return
}
# recreate this object (`$_`) with 2 new properties, `Division` and `Department`
$_ | Select-Object *, #{N='Division';E={$usr.Division}}, #{N='Department';E={$usr.Department}}
} | Export-Csv -Path C:\temp\file2.csv -Encoding UTF8 -NoTypeInformation

Powershell conundrum: how to compare to CSVs and pull matching data from each?

I've got a CSV file with a list of names in a "name" column. In a second CSV I have a list of names in a "name" column, and also their employee IDs in an "employeeid" column.
My desired output is this: take the "name" column in CSV1, compare it to the "name" column in CSV2, and wherever there's a match, take the name from the "name" column of CSV1 and the matching employee ID in CSV2, and create a new CSV3 with a "name" column and corresponding "employeeid" column.
Here is an image describing my question
I've started playing with import-csv to pull each CSV in as a variable, and also tinkered with piping that with select headers, but I don't understand the logic necessary to take username column matches between CSV1 and CSV2 and then combine that with employeeID from CSV2.
Thanks in advance for any guidance you can provide.
Brian
--
Updated 3/19
$csv1 = import-csv -Path "C:\csv1.csv" | select-object -ExpandProperty 'accountname' | Sort-Object | where {$_ -ne ""}
$csv2 = import-csv -Path "C:\csv2.csv" | select 'accountname','employeeid'
$accountNamesFromCSV2 = $csv2 | select-object -ExpandProperty accountname
$compareTheTWo = Compare-Object -ReferenceObject $csv1 -DifferenceObject $accountNamesFromCSV2 -ExcludeDifferent -IncludeEqual -passThru
It's friday so I'll be nice. To do it at the prompt:
$csv2 = import-csv .\bar.csv; Import-CSV .\foo.csv | %{$name1 = $_.name;$id = ($csv2 | ?{$_.Name -eq $name1}).EmployeeID; Add-Member -InputObject $_ -MemberType NoteProperty -Name EmployeeID -Value $id; $_} | select Name, EmployeeID | Export-CSV .\result.csv
Or, a little more human friendly version in a script:
$csv2 = Import-CSV .\bar.csv
$result = New-Object System.Collection.ArrayList
foreach($user in (Import-CSV .\foo.csv)){
$id = ($csv2 | Where-Object{$_.Name -eq $user.Name).EmplyeeID
Add-Member -InputObject $user -MemberType NoteProperty -Name EmployeeID -Value $id
$result.Add($user) | Out-Null
}
$result | Export-CSV .\result.csv -NoTypeInformation

Powershell to CSV compare

Hello I'm trying to use some code I found on here to compare a CSV with Active Directory. I have a csv file with a list of users. I want to check this file and see if anything in the "Email" column from the spreadsheet matches an email address from AD. If it does, I want to list that email address and include the Canonical Name from AD so I can easily see what OU the user account is in.
This is what I'm working with:
$path = "C:\Scripts\Import.csv"
$outpath = "C:\Scripts\Export.csv"
$csv = Import-Csv $path
Import-Module ActiveDirectory
foreach ($line in $csv)
{
$User = Get-ADUser -LDAPFilter "(&(objectclass=user)(mail=$($line.Email)))" -Properties CanonicalName
If ($User -ne $Null) {"User does exist in OU" + $line.Email + $User.CanonicalName}
Else {"User not found in AD OU - " + $line.Email}
}
I've been able to modify this to suit my needs but I'm having some trouble piping the results out to a CSV file. Running the script as it's shown above outputs what I want to the screen but I'd like to have it in a CSV format. If I do something like:
$Results = foreach ($line in $csv)
and then use
$Results | export-CSV $outpath -NotypeInformation
I get the csv created but it just includes a the string value, header for Length and then a numeric value for each line. I can use Out-File to send the results to a txt file, which includes the same results that were displayed on the screen, but I'd really like this to be a csv, not txt file. I believe I need to reference the properties of the csv file and AD in order to build these into my export file but I'm having trouble doing that as I'm not sure how to build in the status of whether the user was found or not.
Any assistance would be appreciated.
UPDATE - Final code
This is the final code I went with. This compares the users in the csv with AD users in the parent and child domain. It uses the email address field to match the users. It grabs the Canonical Name so I can see the OU the user is in and if the user is not found, it reports that in the Canonical Name field.
$path = "$env:userprofile\Desktop\InFile.csv"
$outpath = "$env:userprofile\Desktop\OutFile.csv"
# Importing CSV file
Import-Module ActiveDirectory
$Users = Import-Csv $path |
ForEach-Object {
Write-Progress -Activity "Comparing Imported File to Active Directory" -Status "Processing $($_.Email)"
# Comparing CSV file to Domain.com users
If (
$Value1 = (Get-ADUser -LDAPFilter "(&(objectclass=user)(mail=$($_.Email)))" -server Domain.com -Properties CanonicalName).CanonicalName)
{$_ | Add-Member -MemberType NoteProperty -Name CanonicalName -Value $value1 -PassThru}
# Comparing CSV file to child.Domain.com users
ElseIF (
$Value2 = (Get-ADUser -LDAPFilter "(&(objectclass=user)(mail=$($_.Email)))" -server child.Domain.com-Properties CanonicalName).CanonicalName)
{$_ | Add-Member -MemberType NoteProperty -Name CanonicalName -Value $value2 -PassThru}
# Writing output for users not found in either domain
Else {$_ | Add-Member -MemberType NoteProperty -Name CanonicalName -Value "Email Address not found in Active Directory" -PassThru}
#Exporting to CSV file
New-Object -TypeName pscustomobject -Property #{
Email = $_.Email
CanonicalName = $_.CanonicalName
LastName = $_."Last Name"
FirstName = $_."First Name"
}
} | Select-Object LastName, Firstname, Email, CanonicalName | Sort-Object CanonicalName | Export-CSV $outpath -NoTypeInformation
I'm not sure what resulting CSV should look like, so this code just adds CannonicalName using Calculated Properties to Import.Csv and saves it as Export.Csv.
$path = "C:\Scripts\Import.csv"
$outpath = "C:\Scripts\Export.csv"
Import-Module ActiveDirectory
Import-Csv -Path $path |
Select-Object -Property *, #{
n = 'CanonicalName'
e = {(Get-ADUser -LDAPFilter "(&(objectclass=user)(mail=$($_.Email)))" -Properties CanonicalName).CanonicalName}
} | Export-Csv -Path $outpath -NoTypeInformation
Update
This version will create a new CSV file with 3 columns: UserExistInOu, Email and CanonicalName if any:
Import-Csv -Path $path | ForEach-Object {
$UserExistInOu = $false
if($CanonicalName = (Get-ADUser -LDAPFilter "(&(objectclass=user)(mail=$($_.Email)))" -Properties CanonicalName).CanonicalName)
{
$UserExistInOu = $true
}
New-Object -TypeName pscustomobject -Property #{
UserExistInOu = $UserExistInOu
Email = $_.Email
CanonicalName = $CanonicalName
}
} | Export-Csv -Path $outpath -NoTypeInformation

Create dynamic members of PSObject

This is what I got:
Import-Module ActiveDirectory
$objectCollection = #()
$groups = (Get-ADGroup -Filter *)
foreach ($group in $groups) {
$groupName = ($group.SamAccountName)
$object = (New-Object –Type PSObject)
Add-Member -InputObject $object -MemberType NoteProperty –Name ($groupName) –Value ""
$groupMembers = (Get-ADGroupMember -Identity "$groupName" -Recursive |
Select-Object -ExpandProperty Name)
$object.$groupName = $groupMembers
$objectCollection += $object
}
$objectCollection | Export-Csv -Path C:\Users\administrator\Desktop\test.csv `
-Encoding UTF8 -Delimiter ";" -NoTypeInformation
The goal with this script is to create a CSV file where the AD group name is the header in one column an then all the members of the group listed below on separate lines. Next group is in a new column with the AD-group name as header and so on...
Normally I create as many Members as I need but this time I want it to be dynamic to how many groups there is and the script above only displays the first group in the $groups array.
Any help is appreciated, thanks in advance!
Having each group on a separate column in a CSV file seems illogical to me ; one on each row would IMHO be better (and easier too).
Here is how I would do it:
Import-Module ActiveDirectory
Get-ADGroup -Filter * | ForEach-Object {
[PSCustomObject]#{
Name = $_.samAccountName
Members = (Get-ADGroupMember $_ -Recursive | Select-Object -ExpandProperty Name) -join ","
}
} | Export-Csv -Path "C:\Users\administrator\Desktop\test.csv" -Encoding UTF8 -Delimiter ";" -NoTypeInformation
Output:
"Name";"Members"
"Administrators";"Administrator,..."
"Domain Users";"Administrator,TestUser,..."

Powershell Compile all matching rows from CSV

I have a CSV file with a list of Users and who they are managed by with these headers:
DisplayName,Alias,CA5,Managedby
I want to import this list in powershell and be able to send one email to each manager with the list of accounts (DisplayName,Alias,CA5) that they are listed as the manager of in the managedby field. I can create the email with out issue I need to know how to compile all the lines of the CSV file that should all go to into the same email. With the sample CSV below I should end up with three emails (one each to ManagedByA, ManagedbyB and ManagedByC). The email to ManagedByA would have three lines containing:
DN1 A1
DN2 A2 DL
DN3 A3
My CSV look like this:
DisplayName,Alias,CA5,ManagedBy
DN1,A1,,ManagedByA
DN2,A2,DL,ManagedByA
DN3,A3,,ManagedByA
DN4,A4,,ManagedByB
DN5,A5,,ManagedByB
DN6,A6,DL,ManagedByB
DN7,A7,,ManagedByB
DN8,A8,,ManagedByC
DN9,A9,DL,ManagedByC
DN10,A10,,ManagedByC
My Code (from Mathias R. Jessen):
$Import = Import-CSV "C:\powershell\DL\Reports\DLReportEmail.csv"
### Find unique ManagedBy
$Managers = $Import | Sort-Object -Property ManagedBy -Unique
ForEach ($Manager in $Managers){
$Employees = $Import | Where-Object {$_.ManagedBy -eq $Manager.ManagedBy}
$Body = "DearXXXX, `r`n"
ForEach($Employee in $Employees){
$Alias = $Employee.Alias
$DisplayName = $Employee.DisplayName
$CA5 = $Employee.CA5
$Body += "$DisplayName : $Alias : $CA5 `r`n"
}
$Body += "`r`n"
$Body += "Thanks"
You can import the csv, extract each unique manager name, and then compile a subset of the list by using the ManagedBy values you've already extracted:
$Users = Import-Csv C:\filename.csv
$Managers = $Users | Sort-Object -Property ManagedBy -Unique
for($Manager in $Managers)
{
$Employees = $Users |Where-Object {$_.ManagedBy -eq $Manager.ManagedBy}
// send your email here with the contents of $Employees
}