I have been asked to create a script to put comma (,) after every word in csv cell using powershell. However the actual csv has not been shared with me due to some security reason.
I have created a test csv and tried to put comma (,) after every word (Screen shot 1). I am able to create the script and it is working 100% fine (Screen shot 2). However the actual file size is approx 250 MB. I am assuming if that file has 100s of columns, do I have to mention each column name in the script as I mentioned in the foreach loop. Is there any easy way to accomplish this task without mentioning each column name. Any help would be appreciated. Below is my script that is working fine:
$csv = Import-Csv -Path C:\temp\test.csv
$outcsv = Read-Host "Enter the name of the output csv"
$outfile = "$env:USERPROFILE\Downloads" + "" + $outcsv + ".csv"
$data = #()
foreach ($item in $csv) {
$col1 = $item.Name + ","
$col2 = $item.Location + ","
$col3 = $item.Company + ","
$col4 = $item.Profile + ","
$col5 = $item.Shift + ","
$Properties = [ordered]#{
'Name' = $col1
'Location' = $col2
'Company' = $col3
'Profile' = $col4
'Shift' = $col5
}
$data += New-Object -TypeName PSObject -Property $Properties
}
$data | Export-Csv -Path $outfile -NoTypeInformation
Screen shot 1:
Screen shot 2 with comma (,):
This is an easier way to go about it that could handle the logic dynamically by accessing the object's PSObject.Properties.
$outcsv = Read-Host "Enter the name of the output csv"
if(-not [System.IO.Path]::GetExtension($outcsv)) {
$outcsv = $outcsv + '.csv'
}
$outfile = Join-Path "$env:USERPROFILE\Downloads" -ChildPath $outcsv
Import-Csv -Path C:\temp\test.csv | ForEach-Object { $firstObject = $true } {
if($firstObject) {
# get the property names of the first object
$properties = $_.PSObject.Properties.Name
$firstObject = $false
}
# enumerate each property of the object
foreach($property in $properties) {
# update the value
$_.$property = $_.$property + ','
}
# output the updated object
$_
} | Export-Csv $outfile
Related
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"
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
I'm working in PowerShell with a CSV with 13 incremented columns "access1, access2,..", and I am trying to step through and export "crednum" from each row where the access column is not blank, with a new CSV for each column. I've tried (-ne $null) and (-ne " ") both will just give me the entire content of the crednum column and I have no idea what I am doing wrong.
$a = 1
do {
$column = ("access" + $a)
$outpath = "C:\Test\"
$access = Import-Csv 'C:\import.csv' |
where {$_.$column -ne " "} |
select crednum
$a
$access | Export-Csv ($outpath + $column + ".csv") -NoTypeInformation
$a++
} while ($a -le 13)
An empty string doesn't equal $null and it doesn't equal a single space " ". It equals "", '', or [String]::Empty. However, it's usually best to use the [String]::IsEmptyOrWhitespace() function for this sort of thing because it covers more corner cases such as when the column is null, or a single space, or an empty string.
You're also importing the entire CSV on each loop. That's a waste of effort because the entire file has to be processed every iteration.
Try something like this:
$Columns = 1..12 | ForEach-Object { "access$_" }
$Access = Import-Csv 'C:\import.csv'
foreach ($Column in $Columns) {
$Access |
Where-Object { -not [String]::IsNullOrWhiteSpace($_.$Column) } |
Select-Object -Property crednum |
Export-Csv -LiteralPath ($outpath + $Column + ".csv") -NoTypeInformation
}
I want to compare my CSV File with EXL file.
The EXL file has many columns such as USERID and WAVE. My CSV file has just USERID Column.
it should compare my CSV Column USerID with USERID Column in Exl and checks in which wave the user A in CSV has in EXL file and add a wave column in CSV File called "WAVE” and write the wave Number related to USER A in CSV file.
If no name from CSV file is found in EXL file, write in the Column Wave “NOT Found".
I am not sure what I wrote "Read and Get Values from Excel" helps or not but I have no clue how/what to do further.
$TXTFile = "C:\A.txt"
$CSVFile = "C:\B.csv"
$EXLFIle = "C:\C.xlsx"
#find all CNs in TXT file and list them in CSV File
Select-String -Path $TXTFile -Pattern 'CN=(.*?),' -AllMatches |
Select-Object -Expand Matches |
ForEach-Object { $_.Groups[1].Value } |
select #{L="UserID"; E={$_}} |
Export-CSV $CSVFile -noTypeInformation
# Read and Get Values from Excel
#Create an instance of Excel.Application and Open Excel file
$ObjExcel = New-Object -ComObject Excel.Application
$Workbook = $ObjExcel.Workbooks.Open($EXLFIle)
$Sheet = $workbook.Worksheets.Item($SheetName)
$ObjExcel.Visible = $false
#Count max Rows
$RowMax = ($sheet.UsedRange.rows).count
#Declare the starting positions
$rowUserID,$colUserID = 1,2
$rowWave,$colWave = 1,9
for ($i=1; $i -le $RowMax-1; $i++)
{
$UserID = $Sheet.Cells.Item($rowUserID+$i,$colUserID).text
$Wave = $Sheet.Cells.Item($rowWave+$i,$colWave).text
Write-Host ("USERID: "+$UserID)
Write-Host ("Wave: "+$Wave)
}
$objExcel.quit()
UPDATE
I changed the script in this way, but it does not give me any error or any result. EXL file has 26000 raws. I do not know if it takes too much time or sth is wrong in my script.
$TXTFile = "C:\A.txt"
$CSVFile1 = "C:\A.csv"
$EXLFile = "C:\B.xlsx"
$Result = "C:\Result.csv"
$CSVFile2 = "C:\B.csv"
#find all CNs in TXT file and list them in CSV File
Select-String -Path $TXTFile -Pattern 'CN=(.*?),' -AllMatches |
Select-Object -Expand Matches |
ForEach-Object { $_.Groups[1].Value } |
select #{L="UserID"; E={$_}} |
Export-CSV $CSVFile1 -noTypeInformation
########################################################################
# Convert EXL file to CSV File
$excelwb = New-Object -ComObject excel.application
$workbook = $excelwb.Workbooks.Open($EXLFile)
$workbook.SaveAs($CSVFile2,6)
$workbook.Close($false)
$ExcelWB.quit()
$csv = Import-Csv $CSVFile2 -Delimiter ";"
########################################################################
# We Compare File2 with File1
$file2 = import-csv $CSVFile2
$file1 = import-csv $CSVFile1
$Output = #()
ForEach ($a in $file2)
{
$Match = $file1 | where {$_."User ID" -eq $a.UserID}
If($Match)
{
$Output += New-Object PsObject -Property #{"User ID" =$a.UserID;column9 =$Match.column9}
}
else
{
$Output += New-Object PsObject -Property #{"User ID" =$a.UserID;column9 ="NA"}
}
}
$Output | Export-Csv $Result
Don't export the user IDs in the beginning, just store them in an array, say $UserList and for output create an empty array $out=#(). Now inside your loop, you can do comparison and add the user and wave information to the $out:
if($UserList -contains $UserID) {
$w = $Wave
} else {
$w = "NOT Found"
}
$out += new-object PSObject -Property #{"UserID"=$UserID; "Wave"=$w}
In the end export results:
$out | Export-Csv $CSVFile
Hi all I have written the following code to export the text file content to HTML formatted output, but I am not getting the result as expected can some one help me
function TextToHtml {
$SourceFile = "C:\sample.txt"
$TargetFile = "C:\TestOutput.htm"
$TextData = Get-Content $SourceFile
foreach ($Line in $TextData) {
$LineData = $FileLine + $Line
}
$LineData | ConvertTo-HTML | Out-File $TargetFile
}
ConvertTo-Html turns object properties into values in a list or table. A string only has one property, Length - that's what you see the value of in your output.
Create a new object with $LineData as a property value and you'll get meaningful output
function TextToHtml
{
$SourceFile = "C:\sample.txt"
$TargetFile = "C:\TestOutput.htm"
$TextData = Get-Content $SourceFile
Foreach ($Line in $TextData) {
$LineData = $LineData + $Line
}
New-Object psobject -Property #{Text = $LineData} | ConvertTo-HTML -Property Text | Out-File $TargetFile
}
To make your function more reusable, turn the source and target file paths into parameters.
You also don't need to iterate over each string in $TextData to append them to each other, just use the -join operator:
function TextToHtml
{
param(
[string]$SourceFile = "C:\sample.txt",
[string]$TargetFile = "C:\TestOutput.htm"
)
$TextData = Get-Content $SourceFile
$LineData = $TextData -join ''
New-Object psobject -Property #{Text = $LineData} | ConvertTo-HTML | Out-File $TargetFile
}
If you want to avoid the * header for objects that only have one property, use the -Property parameter with ConvertTo-Html to explicitly select the Text property:
ConvertTo-Html -Property Text
If you want to show each line in it's own table row, skip the concatenation and pipe the strings directly to ConvertTo-Html instead:
function TextToHtml
{
param(
[string]$SourceFile = "C:\sample.txt",
[string]$TargetFile = "C:\TestOutput.htm"
)
Get-Content $SourceFile | ConvertTo-HTML -Property #{Label='Text';Expression={$_}} | Out-File $TargetFile
}
If we go just with the code pasted in the question above. It will give you the value of $FileLine (here it is null or blank) and text from last line in that file.
But if you want to have all lines as well use below code:
function TextToHtml
{
$SourceFile = "C:\sample.txt"
$TargetFile = "C:\TestOutput.htm"
$TextData = Get-Content $SourceFile
Foreach ($Line in $TextData) {
$LineData = $FileLine + $LineData + $Line
}
$LineData | ConvertTo-HTML | Out-File $TargetFile
}