How to select column from CSV table - powershell

I need a script that generates usernames based on the first, last name and adds a couple of random numbers. How do I tell PowerShell to separate the columns and not write them all in one?
This is my current code. I was thinking maybe I can separate the names on the semicolon. And then select a part of them with substring and generate my number, put them together and voila.
$users = Import-Csv -Path C:\Users\username\Desktop\Namen.csv -Header "Vorname","Nachname","Username"
foreach ($user in $users) {
$user -replace ';', ' '
}

It seems that the only thing missing is the -delimiter ";" in your Import-Csv.
You can access/manipulate your data like so:
$csv_file = ".\Namen.csv"
$users = Import-Csv $csv_file -Delimiter ";" -Encoding "default"
foreach ($user in $users) {
$generated_username = $user.Vorname + $user.Nachname + "1234"
Write-Host "Vorname: " $user.Vorname
Write-Host "Nachname: " $user.Nachname
Write-Host "Username: " $user.Username
Write-Host "Generated username: $generated_username"
Write-Host ""
}

Related

Copy CSV values from one CSV file to matching CSV values of another file

I have two CSV files and both have one common column, the EmailAddress header.
The powershell script is supposed to copy the phone number from one csv to the other where the email address is matching.
The first CSV file, users.csv, is a Get-ADUser csv export with the following headers:
"SamAccountName";"DisplayName";"Surname";"GivenName";"telephoneNumber";"EmailAddress"
The second CSV file is an export of our address book and has the following headers:
"RoomNr";"Name";"TelNr";"Cordless";"Fax";"Department";"Title";"EmailAddress"
My goal is to copy the "TelNr" to users.csv, where the the value of "EmailAddress" is equal.
My idea looks like this:
$users = Import-Csv -Path C:\users.csv -Delimiter ";"
$addressbook = Import-Csv -Path C:\addressbook.csv -Delimiter ";"
foreach ($record in $users) {
$mail = $record.EmailAddress
$match = $addressbook | Where-Object {$_.EmailAddress -like $mail}
$record.telephoneNumber = $match.TelNr
}
but it's not working at all. Nothing is written in the file. Any idea where I went wrong?
You're so close..
All that is missing is to output the updated $users object array as CSV file.
$users = Import-Csv -Path 'C:\users.csv' -Delimiter ";"
$addressbook = Import-Csv -Path 'C:\addressbook.csv' -Delimiter ";"
foreach ($record in $users) {
$mail = $record.EmailAddress
$record.telephoneNumber = ($addressbook | Where-Object { $_.EmailAddress -eq $mail }).TelNr
}
# output to new csv file
$users | Export-Csv -Path 'C:\UsersComplete.csv' -Delimiter ';' -NoTypeInformation

Splitting values into two columns powershell csv file

I have a PowerShell script that creates a csv file and neatly separates all user input. I need the remaining output to be split across the two headers and I'm struggling to find out how. Tried lots of different code but had no luck.
$Devices = read-host -Prompt "Enter Full Device Name" | out-file 'C:\Users\Public\Desktop\Devices.csv' -Force
$Find = ", "
$Replace = "`n"
$Arrange = (Get-Content 'C:\Users\Public\Desktop\Devices.csv') -replace "$Find","$Replace" | Set-Content 'C:\Users\Public\Desktop\Devices.csv' -Force
$CSV = import-csv 'C:\Users\Public\Desktop\Devices.csv' -Header "Firstname","Lastname"
$CSV | Export-Csv -NoTypeInformation 'C:\Users\Public\Desktop\Devices.csv'
$import = Import-Csv 'C:\Users\Public\Desktop\Devices.csv'
This is the output I currently have in the CSV:
This is the output I am after:
Could almost do with a foreach loop as the first and last names are likely to change as these are inputted using a variable
any help is appreciated.
Export-Csv exports 1 column per distinct property of the input - so to get 2 columns, you need to pipe an object with 2 properties to Export-Csv.
# read device names, split into individual strings
$devices = Read-Host -Prompt "Enter Full Device Name(s)"
$devices = $devices -split ',\s*' |ForEach-Object Trim
# now create one object per device name
$records = $devices |ForEach-Object {
# start by splitting the string into 2 on the first `-`
$FirstName,$LastName = $_ -split '-',2
# now create the object
[pscustomobject]#{
FirstName = $FirstName
LastName = $LastName
}
}
# ... and finally, export to CSV
$records |Export-Csv 'C:\Users\Public\Desktop\Devices.csv' -NoTypeInformation
If you want to retain the - as part of the FirstName value, change this line:
$FirstName,$LastName = $_ -split '-',2
to:
$FirstName,$LastName = $_ -split '(?<=-)',2
Try this out. Since I don't know what your input file looks like there might be some redundant steps in there. Feel free to modify the code to remove any redundant lines if you feel like.
$Devices = read-host -Prompt "Enter Full Device Name" | out-file 'C:\Users\Public\Desktop\Devices.csv' -Force
$Find = ", "
$Replace = "`n"
$Arrange = (Get-Content 'C:\Users\Public\Desktop\Devices.csv') -replace "$Find","$Replace" | Set-Content 'C:\Users\Public\Desktop\Devices.csv' -Force
$CSV = import-csv 'C:\Users\Public\Desktop\Devices.csv' -Header "Firstname","Lastname"
$X = $CSV | select -Skip 1
$y = $x -replace '-','-,' # this adds a comma so that the values are in different columns
$y | Export-Csv -NoTypeInformation 'C:\Users\Public\Desktop\Devices.csv'
$import = Import-Csv 'C:\Users\Public\Desktop\Devices.csv' -Header "Firstname","Lastname"

Powershell | Import .csv file

I want to import .csv file in Powershell. It is only one line in the CSV, which is structured as follows: Text;Text;Text...
This is what i have tried before:
$folder_csv = 'C:\Users\Win_User\Desktop\Folder\CSV_Files'
$files = Get-ChildItem $folder_csv -File -Filter *.csv
foreach ($file in $files) {
$Split_content = $file.split(";")
$timestamp = $($Split_content[0])
$User = $($Split_content[1])
$PC = $($Split_content[2])
$Software = $($Split_content[3]).Substring(1)
}
Write-Host $timestamp + " " + $User + " " + $PC + " " + $Software
I get the following Error Message: "Method invocation failed because [System.IO.FileInfo] does not contain a method named 'split'" .
Is there a better way to imort a csv file and safe each value in a seperate varibale?
Thanks for your help.
Your example file is not containing a header so I guess that's your problem. Then you need to specify it manually when Importing the CSV file. This code works only for when you have one row, if you have multiple rows it will just overwrite the variables and keep the last one. But feel free to change that.
$Header = 'timestamp','User','PC','Software'
$data = Import-Csv -Path .\testcsv.csv -Delimiter ';' -Header $Header
foreach ($row in $data) {
$timestamp = $row.timestamp
$User = $row.User
$PC = $row.PC
$Software = $row.Software
}
$timestamp
$User
$PC
$Software
$Header = 'Name','Age','Profession'
$data = Import-Csv -Path F:\Temp\NoHeader.csv -Delimiter ',' -Header $Header
$data | select Name, Age, Profession

Check csv file values against every line in another csv file

I have two csv file where I contain data, I need to check if value from CSV 1 exist in CSV 2 and if so then replace this value in file2 with data from file1, if no just skip to another row,
File1.csv
NO;Description
L001;DREAM
L002;CAR
L003;PHONE
L004;HOUSE
L005;PLANE
File2.csv
ID;Name;Status*;Scheduled Start Date;Actual Start Date;Actual End Date;Scheduled End Date;SLA
144862;DREAM;Scheduled;1524031200;;;1524033000;
149137;CAR;Implementation In Progress;1528588800;;;1548968400;
150564;PHONE;Scheduled;1569456000;;;1569542400;
150564;HOUSE;Scheduled;1569456000;;;1569542400;
150564;PLANE;;;;;;
I tried something like that but it is not working for me:
$file1 = Import-Csv "C:\Users\file1.csv" |Select-Object -ExpandProperty Description
$file2 = Import-Csv "C:\Users\file1.csv" |Select-Object -ExpandProperty NO
Import-Csv "C:\Users\file3.csv" |Where-Object {$file1 -like $_.Name} |ForEach-Object {
$_.Name = $file2($_.NO)
} |Out-File "C:\Users\File4.csv"
File4.csv should like that:
ID;Name;Status*;Scheduled Start Date;Actual Start Date;Actual End Date;Scheduled End Date;SLA
144862;L001;Scheduled;1524031200;;;1524033000;
149137;L002;Implementation In Progress;1528588800;;;1548968400;
150564;L003;Scheduled;1569456000;;;1569542400;
150564;L004;Scheduled;1569456000;;;1569542400;
150564;L005;;;;;;
Maybe there is another way to achive my goal! Thank you
Here's one approach you can take:
Import both CSV files with Import-Csv
Create a lookup hash table from the first CSV file, where the Description you want to replace are the keys, and NO are the values.
Go through the second CSV file, and replace any values from the Name column from the hash table, if the key exists. We can use System.Collections.Hashtable.ContainsKey to check if the key exists. This is a constant time O(1) operation, so lookups are fast.
Then we can export the final CSV with Export-Csv. I used -UseQuotes Never to put no " quotes in your output file. This feature is only available in PowerShell 7. For lower PowerShell versions, you can have a look at How to remove all quotations mark in the csv file using powershell script? for other alternatives to removing quotes from a CSV file.
Demo:
$csvFile1 = Import-Csv -Path .\File1.csv -Delimiter ";"
$csvFile2 = Import-Csv -Path .\File2.csv -Delimiter ";"
$ht = #{}
foreach ($item in $csvFile1) {
if (-not [string]::IsNullOrEmpty($item.Description)) {
$ht[$item.Description] = $item.NO
}
}
& {
foreach ($line in $csvFile2) {
if ($ht.ContainsKey($line.Name)) {
$line.Name = $ht[$line.Name]
}
$line
}
} | Export-Csv -Path File4.csv -Delimiter ";" -NoTypeInformation -UseQuotes Never
Or instead of wrapping the foreach loop inside a script block using the Call Operator &, we can use Foreach-Object. You can have a look at about_script_blocks for more information about script blocks.
$csvFile2 | ForEach-Object {
if ($ht.ContainsKey($_.Name)) {
$_.Name = $ht[$_.Name]
}
$_
} | Export-Csv -Path File4.csv -Delimiter ";" -NoTypeInformation -UseQuotes Never
File4.csv
ID;Name;Status*;Scheduled Start Date;Actual Start Date;Actual End Date;Scheduled End Date;SLA
144862;L001;Scheduled;1524031200;;;1524033000;
149137;L002;Implementation In Progress;1528588800;;;1548968400;
150564;L003;Scheduled;1569456000;;;1569542400;
150564;L004;Scheduled;1569456000;;;1569542400;
150564;L005;;;;;;
Update
For handling multiple values with the same Name, we can transform the above to use a hash table of System.Management.Automation.PSCustomObject, where we have two properties Count to keep track of the current item we're seeing and NO which is an array of numbers:
$csvFile1 = Import-Csv -Path .\File1.csv -Delimiter ";"
$csvFile2 = Import-Csv -Path .\File2.csv -Delimiter ";"
$ht = #{}
foreach ($row in $csvFile1) {
if (-not $ht.ContainsKey($row.Description) -and
-not [string]::IsNullOrEmpty($item.Description)) {
$ht[$row.Description] = [PSCustomObject]#{
Count = 0
NO = #()
}
}
$ht[$row.Description].NO += $row.NO
}
& {
foreach ($line in $csvFile2) {
if ($ht.ContainsKey($line.Name)) {
$name = $line.Name
$pos = $ht[$name].Count
$line.Name = $ht[$name].NO[$pos]
$ht[$name].Count += 1
}
$line
}
} | Export-Csv -Path File4.csv -Delimiter ";" -NoTypeInformation -UseQuotes Never
If your files aren't too big, you could do this with a simple ForEach-Object loop:
$csv1 = Import-Csv -Path 'D:\Test\File1.csv' -Delimiter ';'
$result = Import-Csv -Path 'D:\Test\File2.csv' -Delimiter ';' |
ForEach-Object {
$name = $_.Name
$item = $csv1 | Where-Object { $_.Description -eq $name } | Select-Object -First 1
# update the Name property and output the item
if ($item) {
$_.Name = $item.NO
# if you output the row here, the result wil NOT contain rows that did not match
# $_
}
# if on the other hand, you would like to retain the items that didn't match unaltered,
# then output the current row here
$_
}
# output on screen
$result | Format-Table -AutoSize
#output to new CSV file
$result | Export-Csv -Path 'D:\Test\File4.csv' -Delimiter ';' -NoTypeInformation
Result on screen:
ID Name Status* Scheduled Start Date Actual Start Date Actual End Date Scheduled End Date SLA
-- ---- ------- -------------------- ----------------- --------------- ------------------ ---
144862 L001 Scheduled 1524031200 1524033000
149137 L002 Implementation In Progress 1528588800 1548968400
150564 L003 Scheduled 1569456000 1569542400
150564 L004 Scheduled 1569456000 1569542400
150564 L005

Import-CSV and Foreach

I've got a huge comma seperated CSV-list with IP-addresses of my network that I want to run queries against. Example of my CSV input:
172.168.0.1,172.168.0.2,172.168.0.3,172.168.0.4
Etc....
When I run the following code to test for the output:
$filepath = "c:\scripts\servers.csv"
$servers = Import-CSV $filepath -delimiter ","
Foreach ($server in $servers) {
write-host $server
}
I get no output, I think it's because there are no headers specified. I can obviously do a workaround and open the CSV-file and type in all the headers. Are there any other ways to solve this?
You can create the headers on the fly (no need to specify delimiter when the delimiter is a comma):
Import-CSV $filepath -Header IP1,IP2,IP3,IP4 | Foreach-Object{
Write-Host $_.IP1
Write-Host $_.IP2
...
}
$IP_Array = (Get-Content test2.csv)[0].split(",")
foreach ( $IP in $IP_Array){
$IP
}
Get-content Filename returns an array of strings for each line.
On the first string only, I split it based on ",". Dumping it into $IP_Array.
$IP_Array = (Get-Content test2.csv)[0].split(",")
foreach ( $IP in $IP_Array){
if ($IP -eq "2.2.2.2") {
Write-Host "Found $IP"
}
}
Solution is to change Delimiter.
Content of the csv file -> Note .. Also space and , in value
Values are 6 Dutch word aap,noot,mies,Piet, Gijs, Jan
Col1;Col2;Col3
a,ap;noo,t;mi es
P,iet;G ,ijs;Ja ,n
$csv = Import-Csv C:\TejaCopy.csv -Delimiter ';'
Answer:
Write-Host $csv
#{Col1=a,ap; Col2=noo,t; Col3=mi es} #{Col1=P,iet; Col2=G ,ijs; Col3=Ja ,n}
It is possible to read a CSV file and use other Delimiter to separate each column.
It worked for my script :-)
$filepath = ".\ADcomputerslist.csv"
$servers = Import-CSV $filepath -delimiter ","
Foreach ($entry in $servers) { write-host $entry.name }
also can replace stupid file with object.
$servers = Get-ADComputer -Filter * -Property * | Select-Object Name,OperatingSystem,OperatingSystemVersion,ipv4Address
Foreach ($entry in $servers) { write-host $entry.name }