I want to insert a blank new line when exporting to CSV, but what I get is "1" inserted instead of blank new line. Here is the code I am using:
foreach($Group in $Groups) {
Get-QADGroupMember $Group | select Name | Export-CSV C:\Users\Nikhil.Tamhankar\Desktop\temp\GroupsInfo.CSV -NoTypeInformation -Append -Encoding UTF8 -UseCulture
$newLine = "`n"
$newLine | Export-CSV C:\Users\Nikhil.Tamhankar\Desktop\temp\GroupsInfo.CSV -NoTypeInformation -Append -Encoding UTF8 -UseCulture
}
Please suggest how I can get a blank new line inserted after every entry made.
It looks like your code is just outputting a single column of group names. If that is the case then I would not even bother with CSV output at that point and just use Set-Content. Adding in the newline then would be fairly easy.
$Groups | ForEach-Object{
(Get-QADGroupMember $_ | Select-Object -ExpandProperty Name) + "`n"
} | Set-Content C:\Users\Nikhil.Tamhankar\Desktop\temp\GroupsInfo.CSV -Encoding UTF8
I used a more pipeline friendly foreach-object loop so you don't have to keep using append.
Export-Csv tries to "discover" the properties of the object, in this case a string - which only has one property, the Length - which happens to be 1.
Use Add-Content or Out-File -Append -NoNewline (version 5 only) to append to an existing file:
"" |Add-Content -Path C:\Users\Nikhil.Tamhankar\Desktop\temp\GroupsInfo.CSV
Related
I am trying to compare the string of two CSV files. If the string from the 2nd CSV file occurs in the 1st CSV file, the corresponding line in the 1st CSV file should be marked with a label (e.g.: "TestLabel") after the semicolon. The strings contain a lot of special characters. By and large, the comparison already works, I can also already add the label.
Since Powershell is still new to me and this is my first script, the following question still arises. How can I set my text "TestLabel" to a certain place in an uncomplicated way? Here, for example, in the next empty field between the semicolons?
CSV1 contains:
Testdefinition;Stichwörter;Stichwörter;Stichwörter;Stichwörter;Stichwörter
It is just a normal text (with round brackets).Test: success;ExistingLabel;;;;
This is a second text;;;
Another text;ExistingLabel;;;;
One more text for the testing - success;ExistingLabel;;;;
CSV2 contains:
Testdefinition;Stichwörter;Stichwörter;Stichwörter;Stichwörter;Stichwörter
It is just a normal text (with round brackets).Test: success
One more text for the testing - success
My script so far:
$header='Testdefinition', 'Stichwörter1', 'Stichwörter2', 'Stichwörter3', 'Stichwörter4', 'Stichwörter5'
$exportheader="Testdefinition;Stichwörter;Stichwörter;Stichwörter;Stichwörter;Stichwörter"
$path1='D:\data\.....test.csv'
$path2='D:\data\.....test_failed.csv'
$wfile='temp1.csv'
$wfile2='temp2.csv'
Get-Content $path1 | Select-Object -Skip 1 | Set-Content $wfile -Encoding UTF8
Get-Content $path2 | Select-Object -Skip 1 | Set-Content $wfile2 -Encoding UTF8
$file1=Import-CSV -Path $wfile -Delimiter ";" -Header $header
$file2=Import-CSV -Path $wfile2 -Delimiter ";" -Header $header
$exportfile='test.csv'
#$exportfile=$file1
$file1 | Get-Member
$file2 | Get-Member
$file1 | Format-Table
$file2 | Format-Table
Write-Output ""
Write-Output "Searching for failed results"
Set-Content $exportfile -Value $exportheader
$file1.Testdefinition | ForEach-Object {
Write-Output "The Testdefinition is: $_ "
$testSearch = $_
$testlinecontent = $file2.Testdefinition | Select-String $testSearch
$testlinenumber = $testlinecontent.LineNumber
if("$_" -eq "$testlinecontent")
{
Write-Output "Testline found: $testlinecontent in Line $testlinenumber"
Write-Output "$_ = $testlinecontent"
$testlineexport = "$_;$testlinenumber;TestLabel"
Write-Output $testlineexport
$testlineexport | Add-Content -Path $exportfile
}
else
{
Write-Output "Testline not found"
$testlineexport = "$_;$testlinenumber;NULL"
Write-Output $testlineexport
$testlineexport | Add-Content -Path $exportfile
}
Write-Output ""
}
$exportCsv = Import-Csv $exportfile -Delimiter ";" -Header $header
$exportCsv | Format-Table
Remove-Item -Path $wfile
Remove-Item -Path $wfile2
I hope you can give me a hint. Thanks in advance!
Assuming the files aren't too big, you can use the following approach based on Compare-Object, which is conceptually clear and relatively simple:
# Read the CSV files into their header row and the array of data rows, as strings.
$header, $rows1 = Get-Content $path1
$null, $rows2 = Get-Content $path2
# Initialize the export file by writing its header
Set-Content -Encoding utf8 $exportfile -Value $exportheader
# Compare the data rows by their first ";"-separated field.
# If the fields match, append ";TestLabel" to the LHS data row before
# passing it through, otherwise pass it as-is, and append to the
# export file.
Compare-Object -PassThru $rows1 $rows2 -IncludeEqual -Property { $_.Split(';')[0] } |
ForEach-Object { if ($_.SideIndicator -eq '==') { $_ + ';TestLabel' } else { $_ } } |
Add-Content $exportfile
Note:
For brevity I've omitted the code to also add a line number.
As you are already aware, PowerShell doesn't support CSV files whose headers contain duplicate column names, given that the column names become property names on import, and must therefore be unique.
I am trying to compare the string of two CSV files. If the string from the 2nd CSV file occurs in the 1st CSV file, the corresponding line in the 1st CSV file should be marked with a label (e.g.: "TestLabel") after the semicolon. The strings contain a lot of special characters. By and large, the comparison already works, I can also already add the label.
Since Powershell is still new to me and this is my first script, the following question still arises. How can I set my text "TestLabel" to a certain place in an uncomplicated way? Here, for example, in the next empty field between the semicolons?
CSV1 contains:
Testdefinition;Stichwörter;Stichwörter;Stichwörter;Stichwörter;Stichwörter
It is just a normal text (with round brackets).Test: success;ExistingLabel;;;;
This is a second text;;;
Another text;ExistingLabel;;;;
One more text for the testing - success;ExistingLabel;;;;
CSV2 contains:
Testdefinition;Stichwörter;Stichwörter;Stichwörter;Stichwörter;Stichwörter
It is just a normal text (with round brackets).Test: success
One more text for the testing - success
My script so far:
$header='Testdefinition', 'Stichwörter1', 'Stichwörter2', 'Stichwörter3', 'Stichwörter4', 'Stichwörter5'
$exportheader="Testdefinition;Stichwörter;Stichwörter;Stichwörter;Stichwörter;Stichwörter"
$path1='D:\data\.....test.csv'
$path2='D:\data\.....test_failed.csv'
$wfile='temp1.csv'
$wfile2='temp2.csv'
Get-Content $path1 | Select-Object -Skip 1 | Set-Content $wfile -Encoding UTF8
Get-Content $path2 | Select-Object -Skip 1 | Set-Content $wfile2 -Encoding UTF8
$file1=Import-CSV -Path $wfile -Delimiter ";" -Header $header
$file2=Import-CSV -Path $wfile2 -Delimiter ";" -Header $header
$exportfile='test.csv'
#$exportfile=$file1
$file1 | Get-Member
$file2 | Get-Member
$file1 | Format-Table
$file2 | Format-Table
Write-Output ""
Write-Output "Searching for failed results"
Set-Content $exportfile -Value $exportheader
$file1.Testdefinition | ForEach-Object {
Write-Output "The Testdefinition is: $_ "
$testSearch = $_
$testlinecontent = $file2.Testdefinition | Select-String $testSearch
$testlinenumber = $testlinecontent.LineNumber
if("$_" -eq "$testlinecontent")
{
Write-Output "Testline found: $testlinecontent in Line $testlinenumber"
Write-Output "$_ = $testlinecontent"
$testlineexport = "$_;$testlinenumber;TestLabel"
Write-Output $testlineexport
$testlineexport | Add-Content -Path $exportfile
}
else
{
Write-Output "Testline not found"
$testlineexport = "$_;$testlinenumber;NULL"
Write-Output $testlineexport
$testlineexport | Add-Content -Path $exportfile
}
Write-Output ""
}
$exportCsv = Import-Csv $exportfile -Delimiter ";" -Header $header
$exportCsv | Format-Table
Remove-Item -Path $wfile
Remove-Item -Path $wfile2
I hope you can give me a hint. Thanks in advance!
Assuming the files aren't too big, you can use the following approach based on Compare-Object, which is conceptually clear and relatively simple:
# Read the CSV files into their header row and the array of data rows, as strings.
$header, $rows1 = Get-Content $path1
$null, $rows2 = Get-Content $path2
# Initialize the export file by writing its header
Set-Content -Encoding utf8 $exportfile -Value $exportheader
# Compare the data rows by their first ";"-separated field.
# If the fields match, append ";TestLabel" to the LHS data row before
# passing it through, otherwise pass it as-is, and append to the
# export file.
Compare-Object -PassThru $rows1 $rows2 -IncludeEqual -Property { $_.Split(';')[0] } |
ForEach-Object { if ($_.SideIndicator -eq '==') { $_ + ';TestLabel' } else { $_ } } |
Add-Content $exportfile
Note:
For brevity I've omitted the code to also add a line number.
As you are already aware, PowerShell doesn't support CSV files whose headers contain duplicate column names, given that the column names become property names on import, and must therefore be unique.
Is there a way to include text qualifiers i.e. "Column 1"|"Column 2" when using PowerShell to export to a csv file?
In the script below I remove the text qualifiers that were already transferred in the file because the first column didn't have any for some odd reason.
Get-MsolUser -all |
Where-Object {($_.IsLicensed -eq "True") -and ($_.Title -notlike "Volunteer") } |
Select-Object Firstname, LastName, Department, Title |
ConvertTo-Csv -NoTypeInformation -Delimiter "|"|
% { $_ -replace '","', "|"} | % { $_ -replace '"', ""} | out-file "$path\$file_name" -fo -en ascii
I think the output may be as you expect but you may be viewing the output file in Excel rather than with a text editor (I used Notepad++). When I tried to reproduce this I used the following code and viewed the output file in a text editor and each column and row of the output has text qualifiers as expected. However, when viewing the same file in Excel the first column is displayed by Excel as if it does not have text qualifiers. Here's the code I ran to test:
"[a known UPN from my tenant]","[a known UPN from my tenant]"|
foreach-object {Get-MsolUser -UserPrincipalName $_} |
Where-Object {($_.IsLicensed -eq "True") -and ($_.Title -notlike "Volunteer")} |
Select-Object Firstname, LastName, Department, Title |
ConvertTo-Csv -NoTypeInformation -Delimiter "|" |
out-file $path\$file_name" -fo -en ascii
The issue with text qualifiers missing in the first column first occurred 'before' I specified the -delimiter parameter, my code above is a bit of a fix and mashup of two methods of fixing that issue, and a bit redundant.
I'm able to generate the intended results with the script below:
$MyData = import-csv \\TestPath\licenses_v2.csv -delimiter '|' |
select-object FirstName,LastName,Department,Title,#{expression={'Office 365 AD'}};
Write-DbaDataTable -sqlinstance $server -database $database -table $table -inputobject $MyData -KeepNulls;
So I am looking at breaking up a CSV using Powershell. The CSV is delmited by | which isn't a problem, and I am looking to break it up into multiple smaller csvs while retaining the original. The breaks would occur based off of the value in a single column containing one of a list of values.
What I have done so far is to import the csv (delimited by |) and then
foreach($line in $csv) {
if($columnValue -like $target1) {
export-csv filename1.csv -Delimiter `| $line -append)}
elseif($columnValue -like $target2) {
export-csv filename2.csv -Delimiter `| $line -append)}
etc.
However I do not think it is exporting correctly, and I do not want there to be the quotes (and yes I know this is standard but I do not want them) Also I want the header from the original csv to be applied to the child csvs and its not being applied.
sorry if theres a better way to format the code still new here
Here is where I suggest the awesomeness of the Switch cmdlet. It compares something against multiple potential matches, and executes those matches where appropriate.
Switch($csv){
{$_.column -match $target1} {$_ | Export-CSV filename1.csv -append -delimiter '|'}
{$_.column -match $target2} {$_ | Export-CSV filename2.csv -append -delimiter '|'}
{$_.column -match $target3} {$_ | Export-CSV filename3.csv -append -delimiter '|'}
}
$data = import-csv $csvfile
$data | ?{$_.val -eq $criteria1} | export-csv -path "File1.csv"
$data | ?{$_.val -eq $criteria2} | export-csv -path "File2.csv"
I'm extracting fields from Active Directory and piping that into a .csv file, My Select-Object command returns the fields by name. My problem is some of these fields contain carriage return and line feed information I want to remove before piping it into the .csv
Example:
Select-Object SamAccountName,displayName,info | ConvertTo-CSV -NoTypeInformation |
Out-File -Append -FilePath $Filepath -Encoding unicode
How can I intercept and amend the 'info' field before firing it to .csv?
Thanks.
You could remove carriage return and line feed using regex. Try next snippet:
Select-Object -property SamAccountName, DisplayName, Info |
% {
$_.SamAccountName = [regex]::Replace($_.SamAccountName, "(`n|`r)+"," ", "Multiline");
$_.DisplayName= [regex]::Replace($_.DisplayName, "(`n|`r)+"," ", "Multiline");
$_.Info = [regex]::Replace($_.Info, "(`n|`r)+"," ", "Multiline");
return $_;
} |
ConvertTo-CSV -NoTypeInformation |
Out-File -Append -FilePath $Filepath -Encoding unicode
You can intercept the output using a calculated property:
Select-Object SamAccountName,displayName,{$_.info.replace("`r", "").replace("`n", "")}
| ConvertTo-CSV -NoTypeInformation
| Out-File -Append -FilePath $Filepath -Encoding unicode
The backtick ` allows you to insert special characters `r is carriage return and `n is new line.