Processing text file and write it content to HTML output - powershell

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
}

Related

Compare a Column from CSV with a Column in EXL and add the result to my CSV File

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

Manipulate CSV value without knowing column names [duplicate]

I want to process a csv file in powershell, but I don't know what the column headings in the CSV file will be when it is processed.
For example:
$path = "d:\scratch\export.csv"
$csv = Import-csv -path $path
foreach($line in $csv)
{
foreach ($head in $line | get-member | where-object {$_.MemberType -eq "NoteProperty"} | select Definition)
{
#pseudocode...
doSomething($head.columnName, $head.value)
}
}
How do I loop through the line in the csv file, getting the name of the column and the value? Or is there another way I should be doing this (like not using Import-csv)?
Import-Csv $path | Foreach-Object {
foreach ($property in $_.PSObject.Properties)
{
doSomething $property.Name, $property.Value
}
}
A slightly other way of iterating through each column of each line of a CSV-file would be
$path = "d:\scratch\export.csv"
$csv = Import-Csv -path $path
foreach($line in $csv)
{
$properties = $line | Get-Member -MemberType Properties
for($i=0; $i -lt $properties.Count;$i++)
{
$column = $properties[$i]
$columnvalue = $line | Select -ExpandProperty $column.Name
# doSomething $column.Name $columnvalue
# doSomething $i $columnvalue
}
}
so you have the choice: you can use either $column.Name to get the name of the column, or $i to get the number of the column
$header3 = #("Field_1","Field_2","Field_3","Field_4","Field_5")
Import-Csv $fileName -Header $header3 -Delimiter "`t" | select -skip 3 | Foreach-Object {
$record = $indexName
foreach ($property in $_.PSObject.Properties){
#doSomething $property.Name, $property.Value
if($property.Name -like '*TextWrittenAsNumber*'){
$record = $record + "," + '"' + $property.Value + '"'
}
else{
$record = $record + "," + $property.Value
}
}
$array.add($record) | out-null
#write-host $record
}

try to determine the max number of character in each column

I have written a script that tries to determine the max no. of character for each column. This is what I wrote:
$path = 'folder path'
$file = Get-ChildItem $path\*
$FileContent = foreach ($files in $file) {
$FileHeader = #( (Get-Content $files -First 1).Split($delimiter) )
$importcsv = #( Import-Csv $files -Delimiter "$delimiter" )
for ($i=0; $i -lt $FileHeader.Length; $i++) {
#select each column
$Column = #( $importcsv | select $FileHeader[$i] )
#find the max no. of character
$MaxChar = #(($Column[$i] |
Select -ExpandProperty $FileHeader[$i] |
Measure-Object -Maximum -Property Length).Maximum)
$output = New-Object PSObject
$output | Add-Member NoteProperty FullName ($files.FullName)
$output | Add-Member NoteProperty FileName ($files.Name)
$output | Add-Member NoteProperty Time (Get-Date -Format s)
$output | Add-Member NoteProperty FileHeader ($($FileHeader[$i]))
$output | Add-Member NoteProperty MaxCharacter ($($MaxChar[$i]))
Write-Output $output
}
}
The script above is just part of it, so $delimiter is already defined. And finally I will export the result as CSV.
The script runs without any error, but when I open the file it only gives me the first column/header the max no. of character, and the rest of column/header are missing.
The perfect result will be showing each column/header the max no. of character.
Is something wrong with my loop?
my boss is trying to create an automate process to finding all the information from the raw data and use those information to upload to the database, so part of the script that is missing is about determine the delimiter of the raw file, the $CleanHeader is clean version of $FileHeader (remove all special characters, turn capital letters to small letters), those cleanheaders will be use for headers in the table in the database. and he also want to know the maximum character in each column, so that info can use them in creating the size of the column in the table in the database (he knows this part can be done in sql), but he ask me whether it can be done in PowerShell or not.
This should work:
$ht = #{}
# import a CSV and iterate over its rows
Import-Csv $f.FullName -Delimiter "$delimiter" | ForEach-Object {
# iterate over the columns of each row
$_.PSObject.Properties | ForEach-Object {
# update the hashtable if the length of the current column value is greater
# than the value in the hashtable
if ($_.Value.Length -gt $ht[$_.Name]) {
$ht[$_.Name] = $_.Value.Length
}
}
}
# create an object for each key in the hashtable
$date = Get-Date -Format s
$ht.Keys | ForEach-Object {
New-Object -Type PSObject -Property #{
FullName = $f.FullName
Name = $f.Name
Time = $date
FileHeader = $_
MaxCharacter = $ht[$_]
}
}
FileHeader[$i] was returning the column name with quotes : "ColumnName" instead of ColumnName
To fix, just add a trim to the line where you pull the header :
$FileHeader = #( (Get-Content $files -First 1).Split($delimiter).trim('"') )

How to pipe an log file CSV in PowerShell?

I would like to use PowerShell to parse a log, and output to a CSV file.
What is the basic way to accomplish this?
Each log format involves it own logic when doing pattern matching, but I would propose to you something like:
(test.log is something like:
date - context - type - msg)
$file = get-content test.log
$pattern = '^(.*) - (.*) - (.*) - (.*)$'
$findings = $file | select-string -pattern $pattern
$lines = foreach($f in $findings) {
if ($f -match $pattern) {
$line = #{
'date' = $matches[1]
'context' = $matches[2]
'level' = $matches[3]
'message' = $matches[4]
}
new-object -typename psobject -property $line
}
}
$lines | export-csv -notypeinformation -delimiter ';' -path 'test.csv'
Get-Content | do something | Export-CSV

Powershell search hits within column & return column name

I'm looking for a way (if possible) to find any hits within any column that contain a ";" semicolon character and return the column/field name.
I'm basically loading in a DAT delimited text file (or csv). The headers will be different each time, but I'm basically trying to figure out if I will be expecting any of the columns to contain multi-delimited values within the column such as email CC or BCC.
I'm using a form with a text box to input the DAT/CSV.
$form.Topmost = $True
$form.Add_Shown({$textBox.Select()})
$result = $form.ShowDialog()
if ($result -eq [System.Windows.Forms.DialogResult]::OK)
{
$x = $textBox.Text
$x
}
Here is my code for output file:
Get-Content $x |
foreach {$_ -replace "þ", '"'} |
ConvertFrom-Csv -Delimiter "" |
Out-GridView
I have been able to search a hit on the entire CSV by using:
$FileContent = Get-Content $x
$Matches = Select-String -InputObject $FileContent -Pattern ';' -AllMatches
$Matches.Matches.Count
The above part does giving me the total number of ";" hits. But I'd rather see which columns hit, I don't really need a total count, just the header name or column number.
I'm using powershell ISE v5.
I would use a Select-String to to find the initial hits which would be quicker than looping through each column and row. You can the loop through the results by converting each found row into a CSV and then an object. All you need to do then is loop though each property and output the results. Something like this:
$file = 'your_file.csv'
$head = Get-Content $file -TotalCount 1
$re = ';'
Select-String $file -Pattern $re | % {
$line = $_
$item = $head + "`n" + $_.line | ConvertFrom-Csv
$item | gm -MemberType NoteProperty | select -ExpandProperty Name | % {
if($item."$_" -match $re) {
New-Object psobject -property #{
Column = $_
Row = $line.Linenumber
Value = $item."$_"
}
}
}
}