Comparing all properties of PSCustomObjects (Excel sheet data) - excel

I am working on a script for PowerShell to import data from 2 separate Excel sheets, compare all properties of these sheets and export a new Excel worksheet with this output.
The purpose of this script is to compare an updated excel sheet with a previous version and spot what has changed, what has been added and possibly even what has been removed.
I have been using the Import-Excel module to handle the first part, and Compare-Object for the data comparison.
As far as I can tell Import-Excel imports the Excel data into a System.Object which is a hashtable of PSCustomObjects. Each PSCustomObject corresponds to a row in the Excel sheet.
I am running the following code:
$global:InputdataA = Import-Excel -Path $InputA -WorkSheetname $InputSheetA
$global:InputdataB = Import-Excel -Path $InputB -WorkSheetname $InputSheetB
$global:ReferenceObject = $InputdataA
$global:DifferenceObject = $InputdataB
$global:InputdataHeadersA = $InputdataA[0].psobject.properties.name
$global:InputdataHeadersB = $InputdataB[0].psobject.properties.name
$props = $InputdataHeadersA
$props += $InputdataHeadersB
$props = $props | Select -Unique
$compareResult = Compare-Object -ReferenceObject $ReferenceObject -DifferenceObject $DifferenceObject -Property $props -PassThru -CaseSensitive
I am using 2 excel files for testing:
Personnel_16_12_2018 - small2.xlsx (previous version)
Personnel_28_11_2018 - small2.xlsx (new version with changes and additions)
The files can be downloaded here:
https://ufile.io/bmstu
https://ufile.io/3z62x
The output I would like to see would be only the 7 entries that have been changed/added, with data from difference object (the new version of the excel sheet) This would represent the latest and "correct" data.
Currently I get an output from the compare-object, containing the 7 entries AND the 6 entries that have been changed from the reference object including side-indicator.
Is it possible to make the compare-object return only the changes or do I have to process the output afterwards?

Based on your additional information and the sample files, you could try something like this:
$oldFile = Import-Excel ".\personnel_28_11_2018---small2.xlsx"
$newFile = Import-Excel ".\personnel_16_12_2018---small2.xlsx"
$properties = "TRIAL_PK", "TRIALCOUNTRY_PK", "TRIALSSITE_PK", "ASSIGNMENT_LVL", "ROLE", "INT_EXT", "START_DATA", "END_DATE", "PERSONNELL_PK", "TITLE", "LAST_NAME", "FIRST_NAME", "ORGANIZATION_NAME"
$result = Compare-Object -ReferenceObject $oldFile -DifferenceObject $newFile -Property $properties -PassThru -CaseSensitive | Where-Object {$_.SideIndicator -eq "=>"}
$result | Select-Object $properties | Export-Excel ".\changed.xlsx"

Related

how to compare two excel sheet using powershell

I have last month excel sheet with following
Current month excel sheet with following
Now i would like find what is new server Name added in current month then list them out as shown below
So far i got following code. any idea would be appreciated ? i will be scheduling this with windows scheduler task .This should be powershell since i will be adding more code later how to pick right excel sheet from SMB share.
i am trying this
$oldbk = Import-Excel -Path '\\hcohesity05\cohesity_reports\2022\7\07-29\Cohesity_FETB_Report-2022-07-29-14-26-48.xlsx'
$newbk = Import-Excel -Path '\\hcohesity05\cohesity_reports\2022\8\08-26\Cohesity_FETB_Report-2022-08-26-14-26-48.xlsx'
$Compare = Compare-Object $oldbk $newbk -Property "Server Name" -includeDifferent -PassThru
$Compare | Export-Excel -Path '.\diff.xlsx'
but getting message
A parameter cannot be found that matches parameter name 'includeDifferent'.
By looking at your code I'm assuming you're only interested in finding the servers not present in the old Excel document, if that's the case you only need Where-Object for filtering:
$oldbk = Import-Excel -Path 'path\to\oldfile.xlsx'
Import-Excel -Path 'path\to\newfile.xlsx' | Where-Object {
$_."Server Name" -notin $oldbk."Server Name"
} | Export-Excel -Path 'path\to\diff.xlsx'
As for the error message, Compare-Object does not have a -IncludeDifferent parameter and shows differences between two objects by default.
$Compare = Compare-Object $oldbk $newbk -Property "Server Name" -PassThru

Powershell - Import-Excel without hidden rows

How do I import an Excel .xlsx file into a Powershell without blank rows? I use Import-Excel to import a file. Just want to import non-hidden rows from the file.
I tried to filter with where-object, like in case blank rows and with out-gridview. Unfortunately, hidden values are imported every time.
# Get all workbook sheets
$sheets = Get-ExcelSheetInfo -Path $path
# Get from all workbooks sheets data
$Report = #()
foreach($sheet in $sheets){
if($sheet.Hidden -eq "Visible"){
$Report += Import-Excel -Path $Path -WorksheetName $sheet.name | Where-Object { $_.PSObject.Properties.Value -ne '' } | Out-GridView -Title "Select rows to pass" -PassThru
}
}

Convert TXTto CSV

I'm working on a project where I need to take a text file and make it an excel file. So far what I've come up with is this.
cls
Remove-Item -path D:\Users\zabin\OneDrive\Desktop\ITS3410\WEEK8\MainWarehouse.csv
Add-Content -path D:\Users\zabin\OneDrive\Desktop\ITS3410\WEEK8\MainWarehouse.csv -Value '"Part_Number","Cost","Price"'
$csvPath = 'D:\Users\zabin\OneDrive\Desktop\ITS3410\WEEK8\MainWarehouse.csv'
#region Excel Test
If (test-path HKLM:SOFTWARE\Classes\Word.Application) {
Write-host "Microsoft Excel installed"
} else {
Write-host "Microsoft Excel not installed"
}
#endregion
#region Patterns
$mainpattern1 = '(?<Partnumber>\d*\s*\w*,)(?<Cost>\d*.\d*),(?<Price>\d*.\d*)'
$mainpattern2 = '(?<Part_number>\d*-\d*-\d*),(?<Cost>\d*.\d*),(?<Price>\d*.\d*)'
#endregion
get-Content 'D:\Users\zabin\OneDrive\Desktop\ITS3410\WEEK8\MainWarehouse.csv' | #grabs the content
Select-String -Pattern $mainpattern1, $mainpattern2 | #selects the patterns
Foreach-Object {
$Part_Number, $Cost, $Price = $_.Matches[0].Groups['Part_number', 'Cost','Price']
[PSCustomObject] #{
part_number = $Part_Number
Cost = $Cost
Price = $Price
}
$objResults | Export-Csv -Path $csvPath -NoTypeInformation -Append
}
some sample data is here
00001143 SP,136.41,227.35
00001223 SP,48.66,81.10
00001236 SP,149.72,249.53
0001-0003-00,100.95,168.25
00015172 W,85.32,142.20
I'm getting the file created and the header values are correct but I'm not sure how to get the values to import.
Continuing from my comment... with the resources and a simple example.
Find-Module -Name '*excel*' | Format-Table -AutoSize
# Results
<#
Version Name Repository Description
------- ---- ---------- -----------
7.1.1 ImportExcel PSGallery PowerShell module to import/export Excel spreadsheets, without Excel....
0.1.12 PSWriteExcel PSGallery Little project to create Excel files without Microsoft Excel being installed.
1.0.2 PSExcel PSGallery Work with Excel without installing Excel
...
0.6.9 ExcelPSLib PSGallery Allow simple creation and manipulation of XLSX file
2.1 Read-ExcelFile PSGallery PowerShell module to import Excel spreadsheets, without Excel....
...
#>
MSExcel will read properly formatted CSV's natively. So, to convert to a true XLS file, use PowerShell, MSOffice COM to open MSExcel with the CSV file, then save it as an XLS format.
$FileName = "$env:temp\Report"
Get-Process |
Export-Csv -UseCulture -Path "$FileName.csv" -NoTypeInformation -Encoding UTF8
$excel = New-Object -ComObject Excel.Application
$excel.Visible = $true
$excel.Workbooks.Open("$FileName.csv").SaveAs("$FileName.xlsx",51)
$excel.Quit()
explorer.exe "/Select,$FileName.xlsx"
Your use case is of course as noted:
Import-Csv -Path 'D:\temp\book1.txt' -header Title, Author
Then using COM as noted above.
I ended up solving this after I asked the question I had alot of flaws in this code
Add-Content -path D:\Users\zabin\OneDrive\Desktop\ITS3410\WEEK8\MainWarehouse.csv -Value '"Part_Number","Cost","Price"'
$csvPath = 'D:\Users\zabin\OneDrive\Desktop\ITS3410\WEEK8\MainWarehouse.csv'
#region Excel Test
If (test-path HKLM:SOFTWARE\Classes\Excel.Application) {#these next few lines will check if excel is installed on the system
Write-host "Microsoft Excel installed"
} else {
Write-host "Microsoft Excel not installed"
}
#endregion
#region Patterns
$mainpattern1 = '(?<Part_number>\d*\s*\w*),(?<Cost>\d*.\d*),(?<Price>\d*.\d*)'#These two line will use REGEX to help seperate the data
$mainpattern2 = '(?<Part_number>\d*-\d*-\d*),(?<Cost>\d*.\d*),(?<Price>\d*.\d*)'
#endregion
get-Content 'D:\Users\zabin\OneDrive\Desktop\ITS3410\WEEK8\Main.rtf' | #grabs the content
Select-String -Pattern $mainpattern2, $mainpattern1 | #selects the patterns
Foreach-Object {
$Part_number, $Cost, $Price = $_.Matches[0].Groups['Part_number', 'Cost','Price'] #Gets the groups of a call to select-string
$results = [PSCustomObject] #{#the list here is what i use to seperate the data onto the CSV file
part_number = $Part_Number
Cost = $Cost
Price = $Price
}
$results | Export-Csv -Path $csvPath -NoTypeInformation -Append #moves the results to the CSV file
}

Consolidate excel workbooks data to csv file from folder using power shell

In a folder i have around 20 excel workbooks,each workbook having MIS for upload excel sheet i want to consolidate all data from each workbook from MIS for upload excel sheet to new csv file using powershell
below is the code which i have tried.But i want Browse for a Folder method.
#Get a list of files to copy from
$Files = GCI 'C:\Users\r.shishodia\Desktop\May 2018' | ?{$_.Extension -Match "xlsx?"} | select -ExpandProperty FullName
#Launch Excel, and make it do as its told (supress confirmations)
$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $True
$Excel.DisplayAlerts = $False
#Open up a new workbook
$Dest = $Excel.Workbooks.Add()
#Loop through files, opening each, selecting the Used range, and only grabbing the first 6 columns of it. Then find next available row on the destination worksheet and paste the data
ForEach($File in $Files[0..20]){
$Source = $Excel.Workbooks.Open($File,$true,$true)
If(($Dest.ActiveSheet.UsedRange.Count -eq 1) -and ([String]::IsNullOrEmpty($Dest.ActiveSheet.Range("A1").Value2))){ #If there is only 1 used cell and it is blank select A1
$Source.WorkSheets.item("MIS for Upload").Activate()
[void]$source.ActiveSheet.Range("A1","R$(($Source.ActiveSheet.UsedRange.Rows|Select -Last 1).Row)").Copy()
[void]$Dest.Activate()
[void]$Dest.ActiveSheet.Range("A1").Select()
}Else{ #If there is data go to the next empty row and select Column A
$Source.WorkSheets.item("MIS for Upload").Activate()
[void]$source.ActiveSheet.Range("A2","R$(($Source.ActiveSheet.UsedRange.Rows|Select -Last 1).Row)").Copy()
[void]$Dest.Activate()
[void]$Dest.ActiveSheet.Range("A$(($Dest.ActiveSheet.UsedRange.Rows|Select -last 1).row+1)").Select()
}
[void]$Dest.ActiveSheet.Paste()
$Source.Close()
}
$Dest.SaveAs("C:\Users\r.shishodia\Desktop\Book2.xlsx",51)
$Dest.close()
$Excel.Quit()
For this purpose you could use ImportExcel module - installation guide included in repo README.
Once you install this module you can easily use Import-Excel cmdlet like this:
$Files = GCI 'C:\Users\r.shishodia\Desktop\May 2018' | ?{$_.Extension -Match "xlsx?"} | select -ExpandProperty FullName
$Temp = #()
ForEach ($File in $Files[0..20]) { # or 19 if you want to have exactly 20 files imported
$Temp += Import-Excel -Path $File -WorksheetName 'MIS for Upload' `
| Select Property0, Property1, Property2, Property3, Property4, Property5
}
To export (you wrote CSV but your destination file format says xlsx):
$Temp | Export-Excel 'C:\Users\r.shishodia\Desktop\Book2.xlsx'
or
$Temp | Export-Csv 'C:\Users\r.shishodia\Desktop\Book2.csv'
That ImportExcel module is really handy ;-)

Last 8 used rows in excel. Powershell

I've looked all over and I can't seem to find an answer for this. Instead of selecting from A1 to G8, I just want it to select the last 8 USED rows in the import it creates. Not sure what to use here.
$pathtsv = "C:\xxxxxx.mdf"
$pathxlsx = "C:\xxxxxxxxxxxxxx.xlsx"
$Excel = New-Object -ComObject "Excel.Application"
$Excel.Visible=$true
$Workbook = $Excel.Workbooks.Open($pathxlsx)
$TempWorkbook = $Excel.Workbooks.Opentext($pathtsv)
$temp = $excel.Workbooks.Item(2)
$temp = $temp.Worksheets.Item(1)
$CopyRange = $temp.Range("A1:G8")
$CopyRange.Copy()
Thanks in advance.
I'd recommend using the ImportExcel module by Doug Finke rather than using Excel as a COM Object. Then the Excel document can be easily imported as a PowerShell object which can then be filtered by Select-Object -Last 8 or $ImportedExcelObject[-8..-1] then reexported in what I assume a Tab Delimited format.
Install-Module ImportExcel
$pathtsv = "C:\xxxxxx.mdf"
$pathxlsx = "C:\xxxxxxxxxxxxxx.xlsx"
Import-Excel $pathxlsx | Select-Object -Last 8 | Export-CSV $pathtsv -Delimiter "`t"
Note: The Install-Module command is included by default in PowerShell 5+.
Here is the updated code for going the opposite way from a tsv to a a specific row and column in an Excel document using the Export-Excel cmdlet from the ImportExcel Module.
Install-Module ImportExcel
$pathtsv = 'C:\xxxxxx.mdf'
$templatexls = 'C:\yyyyyyyyyy.xlsx'
$pathxlsx = 'C:\xxxxxxxxxxxxxx.xlsx'
Copy-Item $templatexls $pathxlsx
Import-CSV $pathtsv -Delimiter "`t" | Select-Object -Last 8 | Export-Excel -Path $pathxlsx -WorksheetName 'Sheet1' -Show -StartRow 3 -StartColumn 1 -NoHeader

Resources