mirror of
https://github.com/dfinke/ImportExcel.git
synced 2025-12-06 00:23:20 +00:00
resolved merge conflicts
This commit is contained in:
@@ -1,22 +1,22 @@
|
||||
Function Add-ConditionalFormatting {
|
||||
<#
|
||||
.Synopsis
|
||||
Adds contitional formatting to worksheet
|
||||
.Example
|
||||
$excel = $avdata | Export-Excel -Path (Join-path $FilePath "\Machines.XLSX" ) -WorksheetName "Server Anti-Virus" -AutoSize -FreezeTopRow -AutoFilter -PassThru
|
||||
<#
|
||||
.Synopsis
|
||||
Adds contitional formatting to worksheet.
|
||||
.Example
|
||||
$excel = $avdata | Export-Excel -Path (Join-path $FilePath "\Machines.XLSX" ) -WorksheetName "Server Anti-Virus" -AutoSize -FreezeTopRow -AutoFilter -PassThru
|
||||
|
||||
Add-ConditionalFormatting -WorkSheet $excel.Workbook.Worksheets[1] -Address "b":b1048576" -ForeGroundColor "RED" -RuleType ContainsText -ConditionValue "2003"
|
||||
Add-ConditionalFormatting -WorkSheet $excel.Workbook.Worksheets[1] -Address "i2:i1048576" -ForeGroundColor "RED" -RuleType ContainsText -ConditionValue "Disabled"
|
||||
$excel.Workbook.Worksheets[1].Cells["D1:G1048576"].Style.Numberformat.Format = [cultureinfo]::CurrentCulture.DateTimeFormat.ShortDatePattern
|
||||
$excel.Workbook.Worksheets[1].Row(1).style.font.bold = $true
|
||||
$excel.Save() ; $excel.Dispose()
|
||||
Add-ConditionalFormatting -WorkSheet $excel.Workbook.Worksheets[1] -Address "b2:b1048576" -ForeGroundColor "RED" -RuleType ContainsText -ConditionValue "2003"
|
||||
Add-ConditionalFormatting -WorkSheet $excel.Workbook.Worksheets[1] -Address "i2:i1048576" -ForeGroundColor "RED" -RuleType ContainsText -ConditionValue "Disabled"
|
||||
$excel.Workbook.Worksheets[1].Cells["D1:G1048576"].Style.Numberformat.Format = [cultureinfo]::CurrentCulture.DateTimeFormat.ShortDatePattern
|
||||
$excel.Workbook.Worksheets[1].Row(1).style.font.bold = $true
|
||||
$excel.Save() ; $excel.Dispose()
|
||||
|
||||
Here Export-Excel is called with the -passThru parameter so the Excel Package object is stored in $Excel
|
||||
The desired worksheet is selected and the then columns B and i are conditially formatted (excluding the top row) to show
|
||||
Fixed formats are then applied to dates in columns D..G and the top row is formatted
|
||||
Finally the workbook is saved and the Excel closed.
|
||||
Here Export-Excel is called with the -passThru parameter so the Excel Package object is stored in $Excel
|
||||
The desired worksheet is selected and the then columns B and i are conditially formatted (excluding the top row) to show red text if
|
||||
the columns contain "2003" or "Disabled respectively. A fixed date formats are then applied to columns D..G, and the top row is formatted.
|
||||
Finally the workbook is saved and the Excel object closed.
|
||||
|
||||
#>
|
||||
#>
|
||||
Param (
|
||||
#The worksheet where the format is to be applied
|
||||
[Parameter(Mandatory = $true, ParameterSetName = "NamedRule")]
|
||||
@@ -70,7 +70,7 @@
|
||||
#Background colour for matching items
|
||||
[System.Drawing.Color]$BackgroundColor,
|
||||
#Background pattern for matching items
|
||||
[OfficeOpenXml.Style.ExcelFillStyle]$BackgroundPattern = [OfficeOpenXml.Style.ExcelFillStyle]::Solid,
|
||||
[OfficeOpenXml.Style.ExcelFillStyle]$BackgroundPattern = [OfficeOpenXml.Style.ExcelFillStyle]::None ,
|
||||
#Secondary colour when a background pattern requires it
|
||||
[System.Drawing.Color]$PatternColor,
|
||||
#Sets the numeric format for matching items
|
||||
@@ -84,13 +84,12 @@
|
||||
#Strikethrough text of matching items
|
||||
[switch]$StrikeThru
|
||||
)
|
||||
#Allow add conditional formatting to work like Set-Format (with single ADDRESS parameter) split it to get worksheet and Range of cells.
|
||||
if ($Address -and -not $WorkSheet -and -not $Range) {
|
||||
#Allow conditional formatting to work like Set-Format (with single ADDRESS parameter), split it to get worksheet and range of cells.
|
||||
If ($Address -and -not $WorkSheet -and -not $Range) {
|
||||
$WorkSheet = $Address.Worksheet[0]
|
||||
$Range = $Address.Address
|
||||
}
|
||||
if ($rule -eq "Databar" -and -not $databarColor) {Write-Warning -Message "-DatabarColor must be specified for the Databar rule type" }
|
||||
if ( $ThreeIconsSet) {$rule = $WorkSheet.ConditionalFormatting.AddThreeIconSet($Range , $ThreeIconsSet)}
|
||||
}
|
||||
If ($ThreeIconsSet) {$rule = $WorkSheet.ConditionalFormatting.AddThreeIconSet($Range , $ThreeIconsSet)}
|
||||
elseif ($FourIconsSet) {$rule = $WorkSheet.ConditionalFormatting.AddFourIconSet( $Range , $FourIconsSet) }
|
||||
elseif ($FiveIconsSet) {$rule = $WorkSheet.ConditionalFormatting.AddFiveIconSet( $Range , $IconType) }
|
||||
elseif ($DataBarColor) {$rule = $WorkSheet.ConditionalFormatting.AddDatabar( $Range , $DataBarColor) }
|
||||
|
||||
367
Compare-WorkSheet.tests.ps1
Normal file
367
Compare-WorkSheet.tests.ps1
Normal file
@@ -0,0 +1,367 @@
|
||||
<<<<<<< HEAD
|
||||
describe "Compare Worksheet" {
|
||||
|
||||
del "$env:temp\server*.xlsx"
|
||||
[System.Collections.ArrayList]$s = get-service | Select-Object -Property *
|
||||
|
||||
$s | Export-Excel -Path $env:temp\server1.xlsx
|
||||
|
||||
#$s is a zero based array, excel rows are 1 based and excel has a header row so Excel rows will be 2 + index in $s
|
||||
$row4Displayname = $s[2].DisplayName
|
||||
$s[2].DisplayName = "Changed from the orginal"
|
||||
|
||||
$d = $s[-1] | Select-Object -Property *
|
||||
$d.DisplayName = "Dummy Service"
|
||||
$d.Name = "Dummy"
|
||||
$s.Insert(3,$d)
|
||||
|
||||
$row6Name = $s[5].name
|
||||
$s.RemoveAt(5)
|
||||
|
||||
$s | Export-Excel -Path $env:temp\server2.xlsx
|
||||
#Assume default worksheet name, (sheet1) and column header for key ("name")
|
||||
$comp = compare-WorkSheet "$env:temp\Server1.xlsx" "$env:temp\Server2.xlsx"
|
||||
|
||||
Context "Simple comparison output" {
|
||||
it "Found the right number of differences " {
|
||||
$comp | should not beNullOrEmpty
|
||||
$comp.Count | should be 4
|
||||
}
|
||||
it "Found the data row with a changed property " {
|
||||
$comp | should not beNullOrEmpty
|
||||
$comp[0]._Side | should be '=>'
|
||||
$comp[1]._Side | should be '<='
|
||||
$comp[0]._Row | should be 4
|
||||
$comp[1]._Row | should be 4
|
||||
$comp[1].Name | should be $comp[0].Name
|
||||
$comp[1].DisplayName | should be $row4Displayname
|
||||
$comp[0].DisplayName | should be "Changed from the orginal"
|
||||
}
|
||||
it "Found the inserted data row " {
|
||||
$comp | should not beNullOrEmpty
|
||||
$comp[2]._Side | should be '=>'
|
||||
$comp[2]._Row | should be 5
|
||||
$comp[2].Name | should be "Dummy"
|
||||
}
|
||||
it "Found the deleted data row " {
|
||||
$comp | should not beNullOrEmpty
|
||||
$comp[3]._Side | should be '<='
|
||||
$comp[3]._Row | should be 6
|
||||
$comp[3].Name | should be $row6Name
|
||||
}
|
||||
}
|
||||
|
||||
$null = compare-WorkSheet "$env:temp\Server1.xlsx" "$env:temp\Server2.xlsx" -BackgroundColor LightGreen
|
||||
$xl1 = Open-ExcelPackage -Path "$env:temp\Server1.xlsx"
|
||||
$xl2 = Open-ExcelPackage -Path "$env:temp\Server2.xlsx"
|
||||
$s1Sheet = $xl1.Workbook.Worksheets[1]
|
||||
$s2Sheet = $xl2.Workbook.Worksheets[1]
|
||||
|
||||
Context "Setting the background to highlight different rows" {
|
||||
it "set the background on the right rows " {
|
||||
$s1Sheet.Cells["4:4"].Style.Fill.BackgroundColor.Rgb | should be "FF90EE90"
|
||||
$s1Sheet.Cells["6:6"].Style.Fill.BackgroundColor.Rgb | should be "FF90EE90"
|
||||
$s2Sheet.Cells["4:4"].Style.Fill.BackgroundColor.Rgb | should be "FF90EE90"
|
||||
$s2Sheet.Cells["5:5"].Style.Fill.BackgroundColor.Rgb | should be "FF90EE90"
|
||||
}
|
||||
it "Didn't set other cells " {
|
||||
$s1Sheet.Cells["3:3"].Style.Fill.BackgroundColor.Rgb | should not be "FF90EE90"
|
||||
$s1Sheet.Cells["F4"].Style.Font.Color.Rgb | should beNullOrEmpty
|
||||
$s2Sheet.Cells["F4"].Style.Font.Color.Rgb | should beNullOrEmpty
|
||||
$s2Sheet.Cells["3:3"].Style.Fill.BackgroundColor.Rgb | should not be "FF90EE90"
|
||||
}
|
||||
}
|
||||
|
||||
Close-ExcelPackage -ExcelPackage $xl1 -NoSave
|
||||
Close-ExcelPackage -ExcelPackage $xl2 -NoSave
|
||||
$null = compare-WorkSheet "$env:temp\Server1.xlsx" "$env:temp\Server2.xlsx" -AllDataBackgroundColor white -BackgroundColor LightGreen -FontColor DarkRed
|
||||
$xl1 = Open-ExcelPackage -Path "$env:temp\Server1.xlsx"
|
||||
$xl2 = Open-ExcelPackage -Path "$env:temp\Server2.xlsx"
|
||||
$s1Sheet = $xl1.Workbook.Worksheets[1]
|
||||
$s2Sheet = $xl2.Workbook.Worksheets[1]
|
||||
|
||||
Context "Setting the forgound to highlight changed properties" {
|
||||
it "Added foreground colour to the right cells " {
|
||||
$s1Sheet.Cells["4:4"].Style.Fill.BackgroundColor.Rgb | should be "FF90EE90"
|
||||
$s1Sheet.Cells["6:6"].Style.Fill.BackgroundColor.Rgb | should be "FF90EE90"
|
||||
$s2Sheet.Cells["4:4"].Style.Fill.BackgroundColor.Rgb | should be "FF90EE90"
|
||||
$s2Sheet.Cells["5:5"].Style.Fill.BackgroundColor.Rgb | should be "FF90EE90"
|
||||
$s1Sheet.Cells["F4"].Style.Font.Color.Rgb | should be "FF8B0000"
|
||||
$s2Sheet.Cells["F4"].Style.Font.Color.Rgb | should be "FF8B0000"
|
||||
}
|
||||
it "Didn't set the foreground on other cells " {
|
||||
$s1Sheet.Cells["F5"].Style.Font.Color.Rgb | should beNullOrEmpty
|
||||
$s2Sheet.Cells["F5"].Style.Font.Color.Rgb | should beNullOrEmpty
|
||||
$s1Sheet.Cells["G4"].Style.Font.Color.Rgb | should beNullOrEmpty
|
||||
$s2Sheet.Cells["G4"].Style.Font.Color.Rgb | should beNullOrEmpty
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Close-ExcelPackage -ExcelPackage $xl1 -NoSave
|
||||
Close-ExcelPackage -ExcelPackage $xl2 -NoSave
|
||||
|
||||
[System.Collections.ArrayList]$s = get-service | Select-Object -Property * -ExcludeProperty Name
|
||||
|
||||
$s | Export-Excel -Path $env:temp\server1.xlsx -WorkSheetname Server1
|
||||
|
||||
#$s is a zero based array, excel rows are 1 based and excel has a header row so Excel rows will be 2 + index in $s
|
||||
$row4Displayname = $s[2].DisplayName
|
||||
$s[2].DisplayName = "Changed from the orginal"
|
||||
|
||||
$d = $s[-1] | Select-Object -Property *
|
||||
$d.DisplayName = "Dummy Service"
|
||||
$d.ServiceName = "Dummy"
|
||||
$s.Insert(3,$d)
|
||||
|
||||
$row6Name = $s[5].ServiceName
|
||||
$s.RemoveAt(5)
|
||||
|
||||
$s[10].ServiceType = "Changed should not matter"
|
||||
|
||||
$s | Select-Object -Property ServiceName, DisplayName, StartType, ServiceType | Export-Excel -Path $env:temp\server2.xlsx -WorkSheetname server2
|
||||
#Assume default worksheet name, (sheet1) and column header for key ("name")
|
||||
$comp = compare-WorkSheet "$env:temp\Server1.xlsx" "$env:temp\Server2.xlsx" -WorkSheetName Server1,Server2 -Key ServiceName -Property DisplayName,StartType -AllDataBackgroundColor AliceBlue -BackgroundColor White -FontColor Red
|
||||
|
||||
$xl1 = Open-ExcelPackage -Path "$env:temp\Server1.xlsx"
|
||||
$xl2 = Open-ExcelPackage -Path "$env:temp\Server2.xlsx"
|
||||
|
||||
$s1Sheet = $xl1.Workbook.Worksheets["server1"]
|
||||
$s2Sheet = $xl2.Workbook.Worksheets["server2"]
|
||||
Context "More complex comparison output etc different worksheet names " {
|
||||
it "Found the right number of differences " {
|
||||
$comp | should not beNullOrEmpty
|
||||
$comp.Count | should be 4
|
||||
}
|
||||
it "Found the data row with a changed property " {
|
||||
$comp | should not beNullOrEmpty
|
||||
$comp[0]._Side | should be '=>'
|
||||
$comp[1]._Side | should be '<='
|
||||
$comp[0]._Row | should be 4
|
||||
$comp[1]._Row | should be 4
|
||||
$comp[1].ServiceName | should be $comp[0].ServiceName
|
||||
$comp[1].DisplayName | should be $row4Displayname
|
||||
$comp[0].DisplayName | should be "Changed from the orginal"
|
||||
}
|
||||
it "Found the inserted data row " {
|
||||
$comp | should not beNullOrEmpty
|
||||
$comp[2]._Side | should be '=>'
|
||||
$comp[2]._Row | should be 5
|
||||
$comp[2].ServiceName | should be "Dummy"
|
||||
}
|
||||
it "Found the deleted data row " {
|
||||
$comp | should not beNullOrEmpty
|
||||
$comp[3]._Side | should be '<='
|
||||
$comp[3]._Row | should be 6
|
||||
$comp[3].ServiceName | should be $row6Name
|
||||
}
|
||||
|
||||
it "set the background on the right rows " {
|
||||
$s1Sheet.Cells["4:4"].Style.Fill.BackgroundColor.Rgb | should be "FFFFFFFF"
|
||||
$s1Sheet.Cells["6:6"].Style.Fill.BackgroundColor.Rgb | should be "FFFFFFFF"
|
||||
$s2Sheet.Cells["4:4"].Style.Fill.BackgroundColor.Rgb | should be "FFFFFFFF"
|
||||
$s2Sheet.Cells["5:5"].Style.Fill.BackgroundColor.Rgb | should be "FFFFFFFF"
|
||||
|
||||
$s1Sheet.Cells["E4"].Style.Font.Color.Rgb | should be "FFFF0000"
|
||||
$s2Sheet.Cells["E4"].Style.Font.Color.Rgb | should be "FFFF0000"
|
||||
}
|
||||
it "Didn't set other cells " {
|
||||
$s1Sheet.Cells["3:3"].Style.Fill.BackgroundColor.Rgb | should not be "FFFFFFFF"
|
||||
$s2Sheet.Cells["3:3"].Style.Fill.BackgroundColor.Rgb | should not be "FFFFFFFF"
|
||||
$s1Sheet.Cells["E5"].Style.Font.Color.Rgb | should beNullOrEmpty
|
||||
$s2Sheet.Cells["E5"].Style.Font.Color.Rgb | should beNullOrEmpty
|
||||
$s1Sheet.Cells["F4"].Style.Font.Color.Rgb | should beNullOrEmpty
|
||||
$s2Sheet.Cells["F4"].Style.Font.Color.Rgb | should beNullOrEmpty
|
||||
}
|
||||
|
||||
}
|
||||
Close-ExcelPackage -ExcelPackage $xl1 -NoSave -Show
|
||||
Close-ExcelPackage -ExcelPackage $xl2 -NoSave -Show
|
||||
|
||||
|
||||
}
|
||||
|
||||
=======
|
||||
describe "Compare Worksheet" {
|
||||
|
||||
del "$env:temp\server*.xlsx"
|
||||
[System.Collections.ArrayList]$s = get-service | Select-Object -Property *
|
||||
|
||||
$s | Export-Excel -Path $env:temp\server1.xlsx
|
||||
|
||||
#$s is a zero based array, excel rows are 1 based and excel has a header row so Excel rows will be 2 + index in $s
|
||||
$row4Displayname = $s[2].DisplayName
|
||||
$s[2].DisplayName = "Changed from the orginal"
|
||||
|
||||
$d = $s[-1] | Select-Object -Property *
|
||||
$d.DisplayName = "Dummy Service"
|
||||
$d.Name = "Dummy"
|
||||
$s.Insert(3,$d)
|
||||
|
||||
$row6Name = $s[5].name
|
||||
$s.RemoveAt(5)
|
||||
|
||||
$s | Export-Excel -Path $env:temp\server2.xlsx
|
||||
#Assume default worksheet name, (sheet1) and column header for key ("name")
|
||||
$comp = compare-WorkSheet "$env:temp\Server1.xlsx" "$env:temp\Server2.xlsx"
|
||||
|
||||
Context "Simple comparison output" {
|
||||
it "Found the right number of differences " {
|
||||
$comp | should not beNullOrEmpty
|
||||
$comp.Count | should be 4
|
||||
}
|
||||
it "Found the data row with a changed property " {
|
||||
$comp | should not beNullOrEmpty
|
||||
$comp[0]._Side | should be '=>'
|
||||
$comp[1]._Side | should be '<='
|
||||
$comp[0]._Row | should be 4
|
||||
$comp[1]._Row | should be 4
|
||||
$comp[1].Name | should be $comp[0].Name
|
||||
$comp[1].DisplayName | should be $row4Displayname
|
||||
$comp[0].DisplayName | should be "Changed from the orginal"
|
||||
}
|
||||
it "Found the inserted data row " {
|
||||
$comp | should not beNullOrEmpty
|
||||
$comp[2]._Side | should be '=>'
|
||||
$comp[2]._Row | should be 5
|
||||
$comp[2].Name | should be "Dummy"
|
||||
}
|
||||
it "Found the deleted data row " {
|
||||
$comp | should not beNullOrEmpty
|
||||
$comp[3]._Side | should be '<='
|
||||
$comp[3]._Row | should be 6
|
||||
$comp[3].Name | should be $row6Name
|
||||
}
|
||||
}
|
||||
|
||||
$null = compare-WorkSheet "$env:temp\Server1.xlsx" "$env:temp\Server2.xlsx" -BackgroundColor LightGreen
|
||||
$xl1 = Open-ExcelPackage -Path "$env:temp\Server1.xlsx"
|
||||
$xl2 = Open-ExcelPackage -Path "$env:temp\Server2.xlsx"
|
||||
$s1Sheet = $xl1.Workbook.Worksheets[1]
|
||||
$s2Sheet = $xl2.Workbook.Worksheets[1]
|
||||
|
||||
Context "Setting the background to highlight different rows" {
|
||||
it "set the background on the right rows " {
|
||||
$s1Sheet.Cells["4:4"].Style.Fill.BackgroundColor.Rgb | should be "FF90EE90"
|
||||
$s1Sheet.Cells["6:6"].Style.Fill.BackgroundColor.Rgb | should be "FF90EE90"
|
||||
$s2Sheet.Cells["4:4"].Style.Fill.BackgroundColor.Rgb | should be "FF90EE90"
|
||||
$s2Sheet.Cells["5:5"].Style.Fill.BackgroundColor.Rgb | should be "FF90EE90"
|
||||
}
|
||||
it "Didn't set other cells " {
|
||||
$s1Sheet.Cells["3:3"].Style.Fill.BackgroundColor.Rgb | should not be "FF90EE90"
|
||||
$s1Sheet.Cells["F4"].Style.Font.Color.Rgb | should beNullOrEmpty
|
||||
$s2Sheet.Cells["F4"].Style.Font.Color.Rgb | should beNullOrEmpty
|
||||
$s2Sheet.Cells["3:3"].Style.Fill.BackgroundColor.Rgb | should not be "FF90EE90"
|
||||
}
|
||||
}
|
||||
|
||||
Close-ExcelPackage -ExcelPackage $xl1 -NoSave
|
||||
Close-ExcelPackage -ExcelPackage $xl2 -NoSave
|
||||
$null = compare-WorkSheet "$env:temp\Server1.xlsx" "$env:temp\Server2.xlsx" -AllDataBackgroundColor white -BackgroundColor LightGreen -FontColor DarkRed
|
||||
$xl1 = Open-ExcelPackage -Path "$env:temp\Server1.xlsx"
|
||||
$xl2 = Open-ExcelPackage -Path "$env:temp\Server2.xlsx"
|
||||
$s1Sheet = $xl1.Workbook.Worksheets[1]
|
||||
$s2Sheet = $xl2.Workbook.Worksheets[1]
|
||||
|
||||
Context "Setting the forgound to highlight changed properties" {
|
||||
it "Added foreground colour to the right cells " {
|
||||
$s1Sheet.Cells["4:4"].Style.Fill.BackgroundColor.Rgb | should be "FF90EE90"
|
||||
$s1Sheet.Cells["6:6"].Style.Fill.BackgroundColor.Rgb | should be "FF90EE90"
|
||||
$s2Sheet.Cells["4:4"].Style.Fill.BackgroundColor.Rgb | should be "FF90EE90"
|
||||
$s2Sheet.Cells["5:5"].Style.Fill.BackgroundColor.Rgb | should be "FF90EE90"
|
||||
$s1Sheet.Cells["F4"].Style.Font.Color.Rgb | should be "FF8B0000"
|
||||
$s2Sheet.Cells["F4"].Style.Font.Color.Rgb | should be "FF8B0000"
|
||||
}
|
||||
it "Didn't set the foreground on other cells " {
|
||||
$s1Sheet.Cells["F5"].Style.Font.Color.Rgb | should beNullOrEmpty
|
||||
$s2Sheet.Cells["F5"].Style.Font.Color.Rgb | should beNullOrEmpty
|
||||
$s1Sheet.Cells["G4"].Style.Font.Color.Rgb | should beNullOrEmpty
|
||||
$s2Sheet.Cells["G4"].Style.Font.Color.Rgb | should beNullOrEmpty
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Close-ExcelPackage -ExcelPackage $xl1 -NoSave
|
||||
Close-ExcelPackage -ExcelPackage $xl2 -NoSave
|
||||
|
||||
[System.Collections.ArrayList]$s = get-service | Select-Object -Property * -ExcludeProperty Name
|
||||
|
||||
$s | Export-Excel -Path $env:temp\server1.xlsx -WorkSheetname Server1
|
||||
|
||||
#$s is a zero based array, excel rows are 1 based and excel has a header row so Excel rows will be 2 + index in $s
|
||||
$row4Displayname = $s[2].DisplayName
|
||||
$s[2].DisplayName = "Changed from the orginal"
|
||||
|
||||
$d = $s[-1] | Select-Object -Property *
|
||||
$d.DisplayName = "Dummy Service"
|
||||
$d.ServiceName = "Dummy"
|
||||
$s.Insert(3,$d)
|
||||
|
||||
$row6Name = $s[5].ServiceName
|
||||
$s.RemoveAt(5)
|
||||
|
||||
$s[10].ServiceType = "Changed should not matter"
|
||||
|
||||
$s | Select-Object -Property ServiceName, DisplayName, StartType, ServiceType | Export-Excel -Path $env:temp\server2.xlsx -WorkSheetname server2
|
||||
#Assume default worksheet name, (sheet1) and column header for key ("name")
|
||||
$comp = compare-WorkSheet "$env:temp\Server1.xlsx" "$env:temp\Server2.xlsx" -WorkSheetName Server1,Server2 -Key ServiceName -Property DisplayName,StartType -AllDataBackgroundColor AliceBlue -BackgroundColor White -FontColor Red
|
||||
|
||||
$xl1 = Open-ExcelPackage -Path "$env:temp\Server1.xlsx"
|
||||
$xl2 = Open-ExcelPackage -Path "$env:temp\Server2.xlsx"
|
||||
|
||||
$s1Sheet = $xl1.Workbook.Worksheets["server1"]
|
||||
$s2Sheet = $xl2.Workbook.Worksheets["server2"]
|
||||
Context "More complex comparison output etc different worksheet names " {
|
||||
it "Found the right number of differences " {
|
||||
$comp | should not beNullOrEmpty
|
||||
$comp.Count | should be 4
|
||||
}
|
||||
it "Found the data row with a changed property " {
|
||||
$comp | should not beNullOrEmpty
|
||||
$comp[0]._Side | should be '=>'
|
||||
$comp[1]._Side | should be '<='
|
||||
$comp[0]._Row | should be 4
|
||||
$comp[1]._Row | should be 4
|
||||
$comp[1].ServiceName | should be $comp[0].ServiceName
|
||||
$comp[1].DisplayName | should be $row4Displayname
|
||||
$comp[0].DisplayName | should be "Changed from the orginal"
|
||||
}
|
||||
it "Found the inserted data row " {
|
||||
$comp | should not beNullOrEmpty
|
||||
$comp[2]._Side | should be '=>'
|
||||
$comp[2]._Row | should be 5
|
||||
$comp[2].ServiceName | should be "Dummy"
|
||||
}
|
||||
it "Found the deleted data row " {
|
||||
$comp | should not beNullOrEmpty
|
||||
$comp[3]._Side | should be '<='
|
||||
$comp[3]._Row | should be 6
|
||||
$comp[3].ServiceName | should be $row6Name
|
||||
}
|
||||
|
||||
it "set the background on the right rows " {
|
||||
$s1Sheet.Cells["4:4"].Style.Fill.BackgroundColor.Rgb | should be "FFFFFFFF"
|
||||
$s1Sheet.Cells["6:6"].Style.Fill.BackgroundColor.Rgb | should be "FFFFFFFF"
|
||||
$s2Sheet.Cells["4:4"].Style.Fill.BackgroundColor.Rgb | should be "FFFFFFFF"
|
||||
$s2Sheet.Cells["5:5"].Style.Fill.BackgroundColor.Rgb | should be "FFFFFFFF"
|
||||
|
||||
$s1Sheet.Cells["E4"].Style.Font.Color.Rgb | should be "FFFF0000"
|
||||
$s2Sheet.Cells["E4"].Style.Font.Color.Rgb | should be "FFFF0000"
|
||||
}
|
||||
it "Didn't set other cells " {
|
||||
$s1Sheet.Cells["3:3"].Style.Fill.BackgroundColor.Rgb | should not be "FFFFFFFF"
|
||||
$s2Sheet.Cells["3:3"].Style.Fill.BackgroundColor.Rgb | should not be "FFFFFFFF"
|
||||
$s1Sheet.Cells["E5"].Style.Font.Color.Rgb | should beNullOrEmpty
|
||||
$s2Sheet.Cells["E5"].Style.Font.Color.Rgb | should beNullOrEmpty
|
||||
$s1Sheet.Cells["F4"].Style.Font.Color.Rgb | should beNullOrEmpty
|
||||
$s2Sheet.Cells["F4"].Style.Font.Color.Rgb | should beNullOrEmpty
|
||||
}
|
||||
|
||||
}
|
||||
Close-ExcelPackage -ExcelPackage $xl1 -NoSave -Show
|
||||
Close-ExcelPackage -ExcelPackage $xl2 -NoSave -Show
|
||||
|
||||
|
||||
}
|
||||
|
||||
>>>>>>> 9f7884f991c80448091ef56853027f64d98b6cc7
|
||||
@@ -1,94 +1,620 @@
|
||||
#Requires -Modules Pester
|
||||
#Requires -Modules Assert
|
||||
#Requires -Modules Pester
|
||||
|
||||
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'
|
||||
|
||||
Import-Module $here -Force -Verbose
|
||||
|
||||
Import-Module $here -Force
|
||||
if (Get-process -Name Excel,xlim -ErrorAction SilentlyContinue) { Write-Warning -Message "You need to close Excel before running the tests." ; return}
|
||||
Describe ExportExcel {
|
||||
|
||||
Context "#Example 1 # Creates and opens a file with the right number of rows and columns" {
|
||||
$path = "$env:TEMP\Test.xlsx"
|
||||
Remove-item -Path $path -ErrorAction SilentlyContinue
|
||||
$processes = Get-Process
|
||||
$propertyNames = $Processes[0].psobject.properties.name
|
||||
$rowcount = $Processes.Count
|
||||
$Processes | Export-Excel $path -show
|
||||
|
||||
it "Created a new file " {
|
||||
Test-Path -Path $path -ErrorAction SilentlyContinue | should be $true
|
||||
}
|
||||
|
||||
$WarningPreference = 'SilentlyContinue'
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
it "Started Excel to display the file " {
|
||||
Get-process -Name Excel,xlim -ErrorAction SilentlyContinue | should not benullorempty
|
||||
}
|
||||
|
||||
Start-Sleep -Seconds 5 ;
|
||||
|
||||
Function Test-isNumeric {
|
||||
Param (
|
||||
[Parameter(ValueFromPipeline)]$x
|
||||
)
|
||||
#Open-ExcelPackage with -Create is tested in Export-Excel
|
||||
#This is a test of using it with -KillExcel
|
||||
#TODO Need to test opening pre-existing file with no -create switch (and graceful failure when file does not exist) somewhere else
|
||||
$Excel = Open-ExcelPackage -Path $path -KillExcel
|
||||
it "Killed Excel when Open-Excelpackage was told to " {
|
||||
Get-process -Name Excel,xlim -ErrorAction SilentlyContinue | should benullorempty
|
||||
}
|
||||
|
||||
Return $x -is [byte] -or $x -is [int16] -or $x -is [int32] -or $x -is [int64] `
|
||||
-or $x -is [sbyte] -or $x -is [uint16] -or $x -is [uint32] -or $x -is [uint64] `
|
||||
-or $x -is [float] -or $x -is [double] -or $x -is [decimal]
|
||||
}
|
||||
it "Created 1 worksheet " {
|
||||
$Excel.Workbook.Worksheets.count | should be 1
|
||||
}
|
||||
|
||||
$fakeData = [PSCustOmobject]@{
|
||||
Property_1_Date = (Get-Date).ToString('d') # US '10/16/2017' BE '16/10/2107'
|
||||
Property_2_Formula = '=SUM(G2:H2)'
|
||||
Property_3_String = 'My String'
|
||||
Property_4_String = 'a'
|
||||
Property_5_IPAddress = '10.10.25.5'
|
||||
Property_6_Number = '0'
|
||||
Property_7_Number = '5'
|
||||
Property_8_Number = '007'
|
||||
Property_9_Number = (33).ToString('F2') # US '33.00' BE '33,00'
|
||||
Property_10_Number = (5/3).ToString('F2') # US '1.67' BE '1,67'
|
||||
Property_11_Number = (15999998/3).ToString('N2') # US '5,333,332.67' BE '5.333.332,67'
|
||||
Property_12_Number = '1.555,83'
|
||||
Property_13_PhoneNr = '+32 44'
|
||||
Property_14_PhoneNr = '+32 4 4444 444'
|
||||
Property_15_PhoneNr = '+3244444444'
|
||||
}
|
||||
|
||||
$Path = 'Test.xlsx'
|
||||
|
||||
Describe 'Export-Excel' {
|
||||
in $TestDrive {
|
||||
Describe 'Number conversion' {
|
||||
Context 'numerical values expected' {
|
||||
#region Create test file
|
||||
$fakeData | Export-Excel -Path $Path
|
||||
|
||||
$Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path)
|
||||
$Excel = New-Object OfficeOpenXml.ExcelPackage $Path
|
||||
$Worksheet = $Excel.Workbook.WorkSheets[1]
|
||||
#endregion
|
||||
|
||||
it 'zero' {
|
||||
$fakeData.Property_6_Number | Should -BeExactly '0'
|
||||
$Worksheet.Cells[2, 6].Text | Should -BeExactly $fakeData.Property_6_Number
|
||||
$Worksheet.Cells[2, 6].Value | Test-isNumeric | Should -Be $true
|
||||
}
|
||||
|
||||
It 'regular number' {
|
||||
$fakeData.Property_7_Number | Should -BeExactly '5'
|
||||
$Worksheet.Cells[2, 7].Text | Should -BeExactly $fakeData.Property_7_Number
|
||||
$Worksheet.Cells[2, 7].Value | Test-isNumeric | Should -Be $true
|
||||
}
|
||||
|
||||
It 'number starting with zero' {
|
||||
$fakeData.Property_8_Number | Should -BeExactly '007'
|
||||
$Worksheet.Cells[2, 8].Text | Should -BeExactly '7'
|
||||
$Worksheet.Cells[2, 8].Value | Test-isNumeric | Should -Be $true
|
||||
}
|
||||
|
||||
It 'decimal number' {
|
||||
# US '33.00' BE '33,00'
|
||||
$fakeData.Property_9_Number | Should -BeExactly (33).ToString('F2')
|
||||
$Worksheet.Cells[2, 9].Text | Should -BeExactly '33'
|
||||
$Worksheet.Cells[2, 9].Value | Test-isNumeric | Should -Be $true
|
||||
|
||||
# US '1.67' BE '1,67'
|
||||
$fakeData.Property_10_Number | Should -BeExactly (5/3).ToString('F2')
|
||||
$Worksheet.Cells[2, 10].Text | Should -BeExactly $fakeData.Property_10_Number
|
||||
$Worksheet.Cells[2, 10].Value | Test-isNumeric | Should -Be $true
|
||||
}
|
||||
|
||||
It 'thousand seperator and decimal number' {
|
||||
# US '5,333,332.67' BE '5.333.332,67'
|
||||
# Excel BE '5333332,67'
|
||||
$fakeData.Property_11_Number | Should -BeExactly (15999998/3).ToString('N2')
|
||||
$Worksheet.Cells[2, 11].Text | Should -BeExactly $fakeData.Property_11_Number
|
||||
$Worksheet.Cells[2, 11].Value | Test-isNumeric | Should -Be $true
|
||||
}
|
||||
$ws = $Excel.Workbook.Worksheets[1]
|
||||
it "Created the worksheet with the expected name, number of rows and number of columns " {
|
||||
$ws.Name | should be "sheet1"
|
||||
$ws.Dimension.Columns | should be $propertyNames.Count
|
||||
$ws.Dimension.Rows | should be ($rowcount + 1)
|
||||
}
|
||||
|
||||
$headingNames = $ws.cells["1:1"].Value
|
||||
it "Created the worksheet with the correct header names " {
|
||||
foreach ($p in $propertyNames) {
|
||||
$headingnames -contains $p | should be $true
|
||||
}
|
||||
}
|
||||
|
||||
it "Formatted the process StartTime field as 'local short date' " {
|
||||
$STHeader = $ws.cells["1:1"].where({$_.Value -eq "StartTime"})[0]
|
||||
$STCell = $STHeader.Address -replace '1$','2'
|
||||
$ws.cells[$stcell].Style.Numberformat.NumFmtID | should be 22
|
||||
}
|
||||
|
||||
it "Formatted the process ID field as 'General' " {
|
||||
$IDHeader = $ws.cells["1:1"].where({$_.Value -eq "ID"})[0]
|
||||
$IDCell = $IDHeader.Address -replace '1$','2'
|
||||
$ws.cells[$IDcell].Style.Numberformat.NumFmtID | should be 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Context " # NoAliasOrScriptPropeties -ExcludeProperty and -DisplayPropertySet work" {
|
||||
$path = "$env:TEMP\Test.xlsx"
|
||||
Remove-item -Path $path -ErrorAction SilentlyContinue
|
||||
$processes = Get-Process
|
||||
$propertyNames = $Processes[0].psobject.properties.where( {$_.MemberType -eq 'Property'}).name
|
||||
$rowcount = $Processes.Count
|
||||
#TestCreating a range with a name which needs illegal chars removing
|
||||
$warnVar = $null
|
||||
$Processes | Export-Excel $path -NoAliasOrScriptPropeties -RangeName "No Spaces" -WarningVariable warnvar -WarningAction SilentlyContinue
|
||||
|
||||
$Excel = Open-ExcelPackage -Path $path
|
||||
$ws = $Excel.Workbook.Worksheets[1]
|
||||
it "Created a new file with alias & Script Properties removed. " {
|
||||
$ws.Name | should be "sheet1"
|
||||
$ws.Dimension.Columns | should be $propertyNames.Count
|
||||
$ws.Dimension.Rows | should be ($rowcount + 1 ) # +1 for the header.
|
||||
}
|
||||
it "Created a Range - even though the name given was invalid. " {
|
||||
$ws.Names["No_spaces"] | should not beNullOrEmpty
|
||||
$ws.Names["No_spaces"].End.Column | should be $propertyNames.Count
|
||||
$ws.names["No_spaces"].End.Row | should be ($rowcount + 1 ) # +1 for the header.
|
||||
$warnVar.Count | should be 1
|
||||
}
|
||||
#This time use clearsheet instead of deleting the file
|
||||
$Processes | Export-Excel $path -NoAliasOrScriptPropeties -ExcludeProperty SafeHandle, modules, MainModule, StartTime, Threads -ClearSheet
|
||||
|
||||
$Excel = Open-ExcelPackage -Path $path
|
||||
$ws = $Excel.Workbook.Worksheets[1]
|
||||
it "Created a new file with a further 5 properties excluded and cleared the old sheet " {
|
||||
$ws.Name | should be "sheet1"
|
||||
$ws.Dimension.Columns | should be ($propertyNames.Count - 5)
|
||||
$ws.Dimension.Rows | should be ($rowcount + 1) # +1 for the header
|
||||
}
|
||||
|
||||
$propertyNames = $Processes[0].psStandardmembers.DefaultDisplayPropertySet.ReferencedPropertyNames
|
||||
Remove-item -Path $path -ErrorAction SilentlyContinue
|
||||
$Processes | Export-Excel $path -DisplayPropertySet
|
||||
|
||||
$Excel = Open-ExcelPackage -Path $path
|
||||
$ws = $Excel.Workbook.Worksheets[1]
|
||||
it "Created a new file with just the members of the Display Property Set " {
|
||||
$ws.Name | should be "sheet1"
|
||||
$ws.Dimension.Columns | should be $propertyNames.Count
|
||||
$ws.Dimension.Rows | should be ($rowcount + 1)
|
||||
}
|
||||
}
|
||||
|
||||
Context "#Example 2 # Exports a list of numbers and applies number format " {
|
||||
|
||||
$path = "$env:TEMP\Test.xlsx"
|
||||
Remove-item -Path $path -ErrorAction SilentlyContinue
|
||||
#testing -ReturnRange switch
|
||||
$returnedRange = Write-Output -1 668 34 777 860 -0.5 119 -0.1 234 788 | Export-Excel -NumberFormat '[Blue]$#,##0.00;[Red]-$#,##0.00' -Path $path -ReturnRange
|
||||
it "Created a new file and returned the expected range " {
|
||||
Test-Path -Path $path -ErrorAction SilentlyContinue | should be $true
|
||||
$returnedRange | should be "A1:A10"
|
||||
}
|
||||
|
||||
$Excel = Open-ExcelPackage -Path $path
|
||||
it "Created 1 worksheet " {
|
||||
$Excel.Workbook.Worksheets.count | should be 1
|
||||
}
|
||||
|
||||
$ws = $Excel.Workbook.Worksheets[1]
|
||||
it "Created the worksheet with the expected name, number of rows and number of columns " {
|
||||
$ws.Name | should be "sheet1"
|
||||
$ws.Dimension.Columns | should be 1
|
||||
$ws.Dimension.Rows | should be 10
|
||||
}
|
||||
|
||||
it "Set the default style for the sheet as expected " {
|
||||
$ws.cells.Style.Numberformat.Format | should be '[Blue]$#,##0.00;[Red]-$#,##0.00'
|
||||
}
|
||||
|
||||
it "Set the default style and value for Cell A1 as expected " {
|
||||
$ws.cells[1,1].Style.Numberformat.Format | should be '[Blue]$#,##0.00;[Red]-$#,##0.00'
|
||||
$ws.cells[1,1].Value | should be -1
|
||||
}
|
||||
}
|
||||
|
||||
Context "#Examples 3 & 4 # Setting cells for different data types Also added test for URI type" {
|
||||
|
||||
$path = "$env:TEMP\Test.xlsx"
|
||||
Remove-item -Path $path -ErrorAction SilentlyContinue
|
||||
[PSCustOmobject][Ordered]@{
|
||||
Date = Get-Date
|
||||
Formula1 = '=SUM(F2:G2)'
|
||||
String1 = 'My String'
|
||||
String2 = 'a'
|
||||
IPAddress = '10.10.25.5'
|
||||
Number1 = '07670'
|
||||
Number2 = '0,26'
|
||||
Number3 = '1.555,83'
|
||||
Number4 = '1.2'
|
||||
Number5 = '-31'
|
||||
PhoneNr1 = '+32 44'
|
||||
PhoneNr2 = '+32 4 4444 444'
|
||||
PhoneNr3 = '+3244444444'
|
||||
Link = [uri]"https://github.com/dfinke/ImportExcel"
|
||||
} | Export-Excel -NoNumberConversion IPAddress, Number1 -Path $path
|
||||
it "Created a new file " {
|
||||
Test-Path -Path $path -ErrorAction SilentlyContinue | should be $true
|
||||
}
|
||||
|
||||
$Excel = Open-ExcelPackage -Path $path
|
||||
it "Created 1 worksheet " {
|
||||
$Excel.Workbook.Worksheets.count | should be 1
|
||||
}
|
||||
|
||||
$ws = $Excel.Workbook.Worksheets[1]
|
||||
it "Created the worksheet with the expected name, number of rows and number of columns " {
|
||||
$ws.Name | should be "sheet1"
|
||||
$ws.Dimension.Columns | should be 14
|
||||
$ws.Dimension.Rows | should be 2
|
||||
}
|
||||
|
||||
it "Set a date in Cell A2 " {
|
||||
$ws.Cells[2,1].Value.Gettype().name | should be 'DateTime'
|
||||
}
|
||||
|
||||
it "Set a formula in Cell B2 " {
|
||||
$ws.Cells[2,2].Formula | should be '=SUM(F2:G2)'
|
||||
}
|
||||
|
||||
it "Set strings in Cells E2 and F2 " {
|
||||
$ws.Cells[2,5].Value.GetType().name | should be 'String'
|
||||
$ws.Cells[2,6].Value.GetType().name | should be 'String'
|
||||
}
|
||||
|
||||
it "Set a number in Cell I2 " {
|
||||
($ws.Cells[2,9].Value -is [valuetype] ) | should be $true
|
||||
}
|
||||
|
||||
it "Set a hyperlink in Cell N2 " {
|
||||
$ws.Cells[2,14].Hyperlink | should be "https://github.com/dfinke/ImportExcel"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Context "# # Setting cells for different data types with -noHeader" {
|
||||
|
||||
$path = "$env:TEMP\Test.xlsx"
|
||||
Remove-item -Path $path -ErrorAction SilentlyContinue
|
||||
[PSCustOmobject][Ordered]@{
|
||||
Date = Get-Date
|
||||
Formula1 = '=SUM(F1:G1)'
|
||||
String1 = 'My String'
|
||||
String2 = 'a'
|
||||
IPAddress = '10.10.25.5'
|
||||
Number1 = '07670'
|
||||
Number2 = '0,26'
|
||||
Number3 = '1.555,83'
|
||||
Number4 = '1.2'
|
||||
Number5 = '-31'
|
||||
PhoneNr1 = '+32 44'
|
||||
PhoneNr2 = '+32 4 4444 444'
|
||||
PhoneNr3 = '+3244444444'
|
||||
Link = [uri]"https://github.com/dfinke/ImportExcel"
|
||||
} | Export-Excel -NoNumberConversion IPAddress, Number1 -Path $path -NoHeader
|
||||
it "Created a new file " {
|
||||
Test-Path -Path $path -ErrorAction SilentlyContinue | should be $true
|
||||
}
|
||||
|
||||
$Excel = Open-ExcelPackage -Path $path
|
||||
it "Created 1 worksheet " {
|
||||
$Excel.Workbook.Worksheets.count | should be 1
|
||||
}
|
||||
|
||||
$ws = $Excel.Workbook.Worksheets[1]
|
||||
it "Created the worksheet with the expected name, number of rows and number of columns " {
|
||||
$ws.Name | should be "sheet1"
|
||||
$ws.Dimension.Columns | should be 14
|
||||
$ws.Dimension.Rows | should be 1
|
||||
}
|
||||
|
||||
it "Set a date in Cell A1 " {
|
||||
$ws.Cells[1,1].Value.Gettype().name | should be 'DateTime'
|
||||
}
|
||||
|
||||
it "Set a formula in Cell B1 " {
|
||||
$ws.Cells[1,2].Formula | should be '=SUM(F1:G1)'
|
||||
}
|
||||
|
||||
it "Set strings in Cells E1 and F1 " {
|
||||
$ws.Cells[1,5].Value.GetType().name | should be 'String'
|
||||
$ws.Cells[1,6].Value.GetType().name | should be 'String'
|
||||
}
|
||||
|
||||
it "Set a number in Cell I1 " {
|
||||
($ws.Cells[1,9].Value -is [valuetype] ) | should be $true
|
||||
}
|
||||
|
||||
it "Set a hyperlink in Cell N1 " {
|
||||
$ws.Cells[1,14].Hyperlink | should be "https://github.com/dfinke/ImportExcel"
|
||||
}
|
||||
}
|
||||
|
||||
Context "#Example 5 # Adding a single conditional format " {
|
||||
### TODO New-ConditionalText doesn't a lot of options in Add-ConditionalFormat.
|
||||
# It would be good to pull the logic out of Export-Excel and have EE call Add-ConditionalFormat.
|
||||
$ct = New-ConditionalText -ConditionalType GreaterThan 525 -ConditionalTextColor DarkRed -BackgroundColor LightPink
|
||||
it "Created a Conditional format description " {
|
||||
$ct.BackgroundColor -is [System.Drawing.Color] | should be $true
|
||||
$ct.ConditionalTextColor -is [System.Drawing.Color] | should be $true
|
||||
$ct.ConditionalType -in [enum]::GetNames( [OfficeOpenXml.ConditionalFormatting.eExcelConditionalFormattingRuleType] ) |
|
||||
should be $true
|
||||
}
|
||||
|
||||
$path = "$env:TEMP\Test.xlsx"
|
||||
Remove-item -Path $path -ErrorAction SilentlyContinue
|
||||
Write-Output 489 668 299 777 860 151 119 497 234 788 | Export-Excel -Path $path -ConditionalText $ct
|
||||
|
||||
it "Created a new file " {
|
||||
Test-Path -Path $path -ErrorAction SilentlyContinue | should be $true
|
||||
}
|
||||
|
||||
#ToDo need to test applying conitional formatting to a pre-existing worksheet
|
||||
$Excel = Open-ExcelPackage -Path $path
|
||||
$ws = $Excel.Workbook.Worksheets[1]
|
||||
|
||||
it "Added one block of conditional formating for the data range " {
|
||||
$ws.ConditionalFormatting.Count | should be 1
|
||||
$ws.ConditionalFormatting[0].Address | should be ($ws.Dimension.Address)
|
||||
}
|
||||
|
||||
$cf = $ws.ConditionalFormatting[0]
|
||||
it "Set the conditional formatting properties correctly " {
|
||||
$cf.Formula | should be $ct.Text
|
||||
$cf.Type.ToString() | should be $ct.ConditionalType
|
||||
#$cf.Style.Fill.BackgroundColor | should be $ct.BackgroundColor
|
||||
# $cf.Style.Font.Color | should be $ct.ConditionalTextColor - have to compare r.g.b
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Context "#Example 6 # Adding multiple conditional formats using short form syntax. " {
|
||||
#this is a test of adding more than one conditional block and using the minimal syntax for new-ConditionalText =
|
||||
$path = "$env:TEMP\Test.xlsx"
|
||||
Remove-item -Path $path -ErrorAction SilentlyContinue
|
||||
|
||||
#Testing -Passthrough
|
||||
$Excel = Get-Service | Select-Object Name, Status, DisplayName, ServiceName |
|
||||
Export-Excel $path -PassThru -ConditionalText $(
|
||||
New-ConditionalText Stop DarkRed LightPink
|
||||
New-ConditionalText Running Blue Cyan
|
||||
)
|
||||
$ws = $Excel.Workbook.Worksheets[1]
|
||||
it "Added two blocks of conditional formating for the data range " {
|
||||
$ws.ConditionalFormatting.Count | should be 2
|
||||
$ws.ConditionalFormatting[0].Address | should be ($ws.Dimension.Address)
|
||||
$ws.ConditionalFormatting[1].Address | should be ($ws.Dimension.Address)
|
||||
}
|
||||
it "Set the conditional formatting properties correctly " {
|
||||
$ws.ConditionalFormatting[0].Text | should be "Stop"
|
||||
$ws.ConditionalFormatting[1].Text | should be "Running"
|
||||
$ws.ConditionalFormatting[0].Type | should be "ContainsText"
|
||||
$ws.ConditionalFormatting[1].Type | should be "ContainsText"
|
||||
#Add RGB Comparison
|
||||
}
|
||||
Close-ExcelPackage -ExcelPackage $Excel
|
||||
}
|
||||
|
||||
context "#Example 7 # Update-FirstObjectProperties works "{
|
||||
$Array = @()
|
||||
|
||||
$Obj1 = [PSCustomObject]@{
|
||||
Member1 = 'First'
|
||||
Member2 = 'Second'
|
||||
}
|
||||
|
||||
$Obj2 = [PSCustomObject]@{
|
||||
Member1 = 'First'
|
||||
Member2 = 'Second'
|
||||
Member3 = 'Third'
|
||||
}
|
||||
|
||||
$Obj3 = [PSCustomObject]@{
|
||||
Member1 = 'First'
|
||||
Member2 = 'Second'
|
||||
Member3 = 'Third'
|
||||
Member4 = 'Fourth'
|
||||
}
|
||||
|
||||
$Array = $Obj1, $Obj2, $Obj3
|
||||
$newarray = $Array | Update-FirstObjectProperties
|
||||
it "Outputs as many objects as it input " {
|
||||
$newarray.Count | should be $Array.Count
|
||||
}
|
||||
it "Added properties to item 0 " {
|
||||
$newarray[0].psobject.Properties.name.Count | should be 4
|
||||
$newarray[0].Member1 | should be 'First'
|
||||
$newarray[0].Member2 | should be 'Second'
|
||||
$newarray[0].Member3 | should beNullOrEmpty
|
||||
$newarray[0].Member4 | should beNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context "#Examples 8 & 9 # Adding Pivot tables and charts from parameters" {
|
||||
$path = "$env:TEMP\Test.xlsx"
|
||||
#This time we are not deleting the XLSX file so this should create a new, named, sheet.
|
||||
$Excel = Get-Process | Select-Object -first 50 -Property Name,cpu,pm,handles,company | Export-Excel $path -WorkSheetname Processes -PassThru
|
||||
#Testing -passthru and adding the Pivot as a second step. Want to save and re-open it ...
|
||||
Export-Excel -ExcelPackage $Excel -WorkSheetname Processes -IncludePivotTable -PivotRows Company -PivotData PM
|
||||
|
||||
$Excel = Open-ExcelPackage $path
|
||||
$PTws = $Excel.Workbook.Worksheets["ProcessesPivotTable"]
|
||||
$wCount = $Excel.Workbook.Worksheets.Count
|
||||
it "Added the named sheet and pivot table to the workbook " {
|
||||
$PTws | should not beNullOrEmpty
|
||||
$PTws.PivotTables.Count | should be 1
|
||||
$Excel.Workbook.Worksheets["Processes"] | should not beNullOrEmpty
|
||||
$Excel.Workbook.Worksheets.Count | should beGreaterThan 2
|
||||
$excel.Workbook.Worksheets["Processes"].Dimension.rows | should be 51 #50 data + 1 header
|
||||
}
|
||||
$pt = $PTws.PivotTables[0]
|
||||
it "Built the expected Pivot table " {
|
||||
$pt.RowFields.Count | should be 1
|
||||
$pt.RowFields[0].Name | should be "Company"
|
||||
$pt.DataFields.Count | should be 1
|
||||
$pt.DataFields[0].Function | should be "Count"
|
||||
$pt.DataFields[0].Field.Name | should be "PM"
|
||||
$PTws.Drawings.Count | should be 0
|
||||
}
|
||||
#using the already open sheet add the pivot chart
|
||||
$warnvar = $null
|
||||
Export-Excel -ExcelPackage $Excel -WorkSheetname Processes -IncludePivotTable -PivotRows Company -PivotData PM -IncludePivotChart -ChartType PieExploded3D -WarningAction SilentlyContinue -WarningVariable warnvar
|
||||
$Excel = Open-ExcelPackage $path
|
||||
it "Added a chart to the pivot table without rebuilding " {
|
||||
$ws = $Excel.Workbook.Worksheets["ProcessesPivotTable"]
|
||||
$Excel.Workbook.Worksheets.Count | should be $wCount
|
||||
$ws.Drawings.count | should be 1
|
||||
$ws.Drawings[0].ChartType.ToString() | should be "PieExploded3D"
|
||||
}
|
||||
it "Generated a message on re-processing the Pivot table " {
|
||||
$warnVar | Should not beNullOrEmpty
|
||||
}
|
||||
$warnVar = $null
|
||||
Get-Process | Select-Object -Last 50 -Property Name,cpu,pm,handles,company | Export-Excel $path -WorkSheetname Processes -Append -IncludePivotTable -PivotRows Company -PivotData PM -IncludePivotChart -ChartType PieExploded3D -WarningAction SilentlyContinue -WarningVariable warnvar
|
||||
$Excel = Open-ExcelPackage $path
|
||||
$pt = $Excel.Workbook.Worksheets["ProcessesPivotTable"].PivotTables[0]
|
||||
it "Appended to the Worksheet and Extended the Pivot table " {
|
||||
$Excel.Workbook.Worksheets.Count | should be $wCount
|
||||
$excel.Workbook.Worksheets["Processes"].Dimension.rows | should be 101 #appended 50 rows to the previous total
|
||||
$pt.CacheDefinition.CacheDefinitionXml.pivotCacheDefinition.cacheSource.worksheetSource.ref |
|
||||
should be "A1:E101"
|
||||
}
|
||||
it "Generated a message on extending the Pivot table " {
|
||||
$warnVar | Should not beNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context " # Add-Worksheet inserted sheets, moved them correctly, and copied a sheet" {
|
||||
$path = "$env:TEMP\Test.xlsx"
|
||||
|
||||
$Excel = Open-ExcelPackage $path
|
||||
#At this point Sheets should be in the order Sheet1, Processes, ProcessesPivotTable
|
||||
$null = Add-WorkSheet -ExcelPackage $Excel -WorkSheetname "Processes" -MoveToEnd # order now Sheet1, ProcessesPivotTable, Processes
|
||||
$null = Add-WorkSheet -ExcelPackage $Excel -WorkSheetname "NewSheet" -MoveAfter "*" -CopySource ($excel.Workbook.Worksheets["Sheet1"]) # Now its NewSheet, Sheet1, ProcessesPivotTable, Processes
|
||||
$null = Add-WorkSheet -ExcelPackage $Excel -WorkSheetname "Sheet1" -MoveAfter "*" # Now its NewSheet, ProcessesPivotTable, Processes, Sheet1
|
||||
$null = Add-WorkSheet -ExcelPackage $Excel -WorkSheetname "Another" -MoveToStart # Now its Another, NewSheet, ProcessesPivotTable, Processes, Sheet1
|
||||
$null = Add-WorkSheet -ExcelPackage $Excel -WorkSheetname "OneLast" -MoveBefore "ProcessesPivotTable" # Now its Another, NewSheet, Onelast, ProcessesPivotTable, Processes, Sheet1
|
||||
Close-ExcelPackage $Excel
|
||||
|
||||
$Excel = Open-ExcelPackage $path
|
||||
|
||||
it "Got the Sheets in the right order " {
|
||||
$excel.Workbook.Worksheets[1].Name | should be "Another"
|
||||
$excel.Workbook.Worksheets[2].Name | should be "NewSheet"
|
||||
$excel.Workbook.Worksheets[3].Name | should be "Onelast"
|
||||
$excel.Workbook.Worksheets[4].Name | should be "ProcessesPivotTable"
|
||||
$excel.Workbook.Worksheets[5].Name | should be "Processes"
|
||||
$excel.Workbook.Worksheets[6].Name | should be "Sheet1"
|
||||
}
|
||||
|
||||
it "Cloned 'Sheet1' to 'NewSheet' "{
|
||||
$newWs = $excel.Workbook.Worksheets["NewSheet"]
|
||||
$newWs.Dimension.Address | should be ($excel.Workbook.Worksheets["Sheet1"].Dimension.Address)
|
||||
$newWs.ConditionalFormatting.Count | should be ($excel.Workbook.Worksheets["Sheet1"].ConditionalFormatting.Count)
|
||||
$newWs.ConditionalFormatting[0].Address.Address | should be ($excel.Workbook.Worksheets["Sheet1"].ConditionalFormatting[0].Address.Address)
|
||||
$newWs.ConditionalFormatting[0].Formula | should be ($excel.Workbook.Worksheets["Sheet1"].ConditionalFormatting[0].Formula)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Context " # Create and append with Start row and Start Column, inc ranges and Pivot table" {
|
||||
$path = "$env:TEMP\Test.xlsx"
|
||||
#Catch warning
|
||||
$warnVar = $null
|
||||
#Test Append with no existing sheet. Test adding a named pivot table from a command line parameter
|
||||
get-process | Select-Object -first 10 -Property Name,cpu,pm,handles,company | export-excel -StartRow 3 -StartColumn 3 -AutoFilter -AutoNameRange -BoldTopRow -IncludePivotTable -PivotRows Company -PivotData PM -PivotTableName 'PTOffset' -Path $path -WorkSheetname withOffset -append
|
||||
get-process | Select-Object -last 10 -Property Name,cpu,pm,handles,company | export-excel -StartRow 3 -StartColumn 3 -AutoFilter -AutoNameRange -BoldTopRow -IncludePivotTable -PivotRows Company -PivotData PM -PivotTableName 'PTOffset' -Path $path -WorkSheetname withOffset -append -WarningAction SilentlyContinue -WarningVariable warnvar
|
||||
$Excel = Open-ExcelPackage $path
|
||||
$dataWs = $Excel.Workbook.Worksheets["withOffset"]
|
||||
$pt = $Excel.Workbook.Worksheets["PTOffset"].PivotTables[0]
|
||||
it "Created and appended to a sheet offset from the top left corner " {
|
||||
$dataWs.Cells[1,1].Value | Should beNullOrEmpty
|
||||
$dataWs.Cells[2,2].Value | Should beNullOrEmpty
|
||||
$dataWs.Cells[3,3].Value | Should not beNullOrEmpty
|
||||
$dataWs.Cells[3,3].Style.Font.Bold | Should be $true
|
||||
$dataWs.Dimension.End.Row | Should be 23
|
||||
$dataWs.names[0].end.row | Should be 23
|
||||
$dataWs.names[0].name | Should be 'Name'
|
||||
$dataWs.names.Count | Should be 6
|
||||
$dataWs.cells[$dataws.Dimension].AutoFilter | Should be true
|
||||
$pt.CacheDefinition.CacheDefinitionXml.pivotCacheDefinition.cacheSource.worksheetSource.ref |
|
||||
Should be "C3:G23"
|
||||
}
|
||||
it "Generated a message on extending the Pivot table " {
|
||||
$warnVar | Should not beNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context "#Example 11 # Create and append with title, inc ranges and Pivot table" {
|
||||
$path = "$env:TEMP\Test.xlsx"
|
||||
$ptDef = [ordered]@{}
|
||||
$ptDef += New-PivotTableDefinition -PivotTableName "PT1" -SourceWorkSheet 'Sheet1' -PivotRows "Status" -PivotData @{'Status' = 'Count'} -PivotFilter "StartType" -IncludePivotChart -ChartType BarClustered3D -ChartTitle "Services by status" -ChartHeight 512 -ChartWidth 768 -ChartRow 10 -ChartColumn 0 -NoLegend
|
||||
$ptDef += New-PivotTableDefinition -PivotTableName "PT2" -SourceWorkSheet 'Sheet2' -PivotRows "Company" -PivotData @{'Company' = 'Count'} -IncludePivotChart -ChartType PieExploded3D -ShowPercent -WarningAction SilentlyContinue
|
||||
|
||||
it "Built a pivot definition using New-PivotTableDefinition " {
|
||||
$ptDef.PT1.SourceWorkSheet | Should be 'Sheet1'
|
||||
$ptDef.PT1.PivotRows | Should be 'Status'
|
||||
$ptDef.PT1.PivotData.Status | Should be 'Count'
|
||||
$ptDef.PT1.PivotFilter | Should be 'StartType'
|
||||
$ptDef.PT1.IncludePivotChart | Should be $true
|
||||
$ptDef.PT1.ChartType.tostring() | Should be 'BarClustered3D'
|
||||
}
|
||||
Remove-Item -Path $path
|
||||
#Catch warning
|
||||
$warnvar = $null
|
||||
Get-Service | Select-Object -Property Status, Name, DisplayName, StartType | Export-Excel -Path $path -AutoSize -TableName "All Services" -TableStyle Medium1 -WarningAction SilentlyContinue -WarningVariable warnvar
|
||||
Get-Process | Select-Object -Property Name, Company, Handles, CPU, VM | Export-Excel -Path $path -AutoSize -WorkSheetname 'sheet2' -TableName "Processes" -TableStyle Light1 -Title "Processes" -TitleFillPattern Solid -TitleBackgroundColor AliceBlue -TitleBold -TitleSize 22 -PivotTableDefinition $ptDef
|
||||
$Excel = Open-ExcelPackage $path
|
||||
$ws1 = $Excel.Workbook.Worksheets["Sheet1"]
|
||||
$ws2 = $Excel.Workbook.Worksheets["Sheet2"]
|
||||
|
||||
|
||||
it "Set Column widths (with autosize) " {
|
||||
$ws1.Column(2).Width | Should not be $ws1.DefaultColWidth
|
||||
$ws2.Column(1).width | Should not be $ws2.DefaultColWidth
|
||||
}
|
||||
|
||||
it "Added tables to both sheets (handling illegal chars) and a title in sheet 2 " {
|
||||
$warnvar.count | Should be 1
|
||||
$ws1.tables.Count | Should be 1
|
||||
$ws2.tables.Count | Should be 1
|
||||
$ws1.Tables[0].Address.Start.Row | Should be 1
|
||||
$ws2.Tables[0].Address.Start.Row | Should be 2 #Title in row 1
|
||||
$ws1.Tables[0].Address.End.Address | Should be $ws1.Dimension.End.Address
|
||||
$ws2.Tables[0].Address.End.Address | Should be $ws2.Dimension.End.Address
|
||||
$ws2.Tables[0].Name | Should be "Processes"
|
||||
$ws2.Tables[0].StyleName | Should be "TableStyleLight1"
|
||||
$ws2.Cells["A1"].Value | Should be "Processes"
|
||||
$ws2.Cells["A1"].Style.Font.Bold | Should be $true
|
||||
$ws2.Cells["A1"].Style.Font.Size | Should be 22
|
||||
$ws2.Cells["A1"].Style.Fill.PatternType.tostring() | Should be "solid"
|
||||
$ws2.Cells["A1"].Style.Fill.BackgroundColor.Rgb | Should be "fff0f8ff"
|
||||
}
|
||||
|
||||
$ptsheet1 = $Excel.Workbook.Worksheets["Pt1"]
|
||||
$ptsheet2 = $Excel.Workbook.Worksheets["Pt2"]
|
||||
$PT1 = $ptsheet1.PivotTables[0]
|
||||
$PT2 = $ptsheet2.PivotTables[0]
|
||||
$PC1 = $ptsheet1.Drawings[0]
|
||||
$PC2 = $ptsheet2.Drawings[0]
|
||||
it "Created the correct pivot tables and charts from the definitions. " {
|
||||
|
||||
$PT1.CacheDefinition.CacheDefinitionXml.pivotCacheDefinition.cacheSource.worksheetSource.ref |
|
||||
Should be ("A1:" + $ws1.Dimension.End.Address)
|
||||
$PT2.CacheDefinition.CacheDefinitionXml.pivotCacheDefinition.cacheSource.worksheetSource.ref |
|
||||
Should be ("A2:" + $ws2.Dimension.End.Address) #Title in row 1
|
||||
|
||||
$pt1.PageFields[0].Name | Should be 'StartType'
|
||||
$pt1.RowFields[0].Name | Should be 'Status'
|
||||
$pt1.DataFields[0].Field.name | Should be 'Status'
|
||||
$pt1.DataFields[0].Function | Should be 'Count'
|
||||
$pc1.ChartType | Should be 'BarClustered3D'
|
||||
$pc1.From.Column | Should be 0 #chart 1 at 0,10 chart 2 at 4,0 (default)
|
||||
$pc2.From.Column | Should be 4
|
||||
$pc1.From.Row | Should be 10
|
||||
$pc2.From.Row | Should be 0
|
||||
$pc1.Legend.Font | should beNullOrEmpty #Best check for legend removed.
|
||||
$pc2.Legend.Font | should not beNullOrEmpty
|
||||
$pc1.Title.Text | Should be 'Services by status'
|
||||
$pc2.DataLabel.ShowPercent | should be $true
|
||||
}
|
||||
}
|
||||
|
||||
Context "#Example 13 # Formatting and another way to do a pivot. " {
|
||||
$path = "$env:TEMP\Test.xlsx"
|
||||
Remove-Item $path
|
||||
$excel = Get-Process | Select-Object -Property Name,Company,Handles,CPU,PM,NPM,WS | Export-Excel -Path $path -ClearSheet -WorkSheetname "Processes" -FreezeTopRowFirstColumn -PassThru
|
||||
$sheet = $excel.Workbook.Worksheets["Processes"]
|
||||
$sheet.Column(1) | Set-Format -Bold -AutoFit
|
||||
$sheet.Column(2) | Set-Format -Width 29 -WrapText
|
||||
$sheet.Column(3) | Set-Format -HorizontalAlignment Right -NFormat "#,###"
|
||||
Set-Format -Address $sheet.Cells["E1:H1048576"] -HorizontalAlignment Right -NFormat "#,###"
|
||||
Set-Format -Address $sheet.Column(4) -HorizontalAlignment Right -NFormat "#,##0.0" -Bold
|
||||
Set-Format -Address $sheet.Row(1) -Bold -HorizontalAlignment Center
|
||||
Add-ConditionalFormatting -WorkSheet $sheet -Range "D2:D1048576" -DataBarColor Red
|
||||
Add-ConditionalFormatting -WorkSheet $sheet -Range "G2:G1048576" -RuleType GreaterThan -ConditionValue "104857600" -ForeGroundColor Red
|
||||
foreach ($c in 5..9) {Set-Format $sheet.Column($c) -AutoFit }
|
||||
Add-PivotTable -PivotTableName "PT_Procs" -ExcelPackage $excel -SourceWorkSheet "Processes" -PivotRows Company -PivotData @{'Name'='Count'} -IncludePivotChart -ChartType ColumnClustered -NoLegend
|
||||
Close-ExcelPackage $excel
|
||||
|
||||
$excel = Open-ExcelPackage $path
|
||||
$sheet = $excel.Workbook.Worksheets["Processes"]
|
||||
|
||||
it "Applied the formating" {
|
||||
$sheet | should not beNullOrEmpty
|
||||
$sheet.Column(1).wdith | should not be $sheet.DefaultColWidth
|
||||
$sheet.Column(7).wdith | should not be $sheet.DefaultColWidth
|
||||
$sheet.Column(1).style.font.bold | should be $true
|
||||
$sheet.Column(2).style.wraptext | should be $true
|
||||
$sheet.Column(2).width | should be 29
|
||||
$sheet.Column(3).style.horizontalalignment | should be 'right'
|
||||
$sheet.Column(4).style.horizontalalignment | should be 'right'
|
||||
$sheet.Cells["A1"].Style.HorizontalAlignment | should be 'Center'
|
||||
$sheet.Cells['E2'].Style.HorizontalAlignment | should be 'right'
|
||||
$sheet.Cells['A1'].Style.Font.Bold | should be $true
|
||||
$sheet.Cells['D2'].Style.Font.Bold | should be $true
|
||||
$sheet.Cells['E2'].style.numberformat.format | should be '#,###'
|
||||
$sheet.Column(3).style.numberformat.format | should be '#,###'
|
||||
$sheet.Column(4).style.numberformat.format | should be '#,##0.0'
|
||||
$sheet.ConditionalFormatting.Count | should be 2
|
||||
$sheet.ConditionalFormatting[0].type | should be 'Databar'
|
||||
$sheet.ConditionalFormatting[0].Color.name | should be 'ffff0000'
|
||||
$sheet.ConditionalFormatting[0].Address.Address | should be 'D2:D1048576'
|
||||
$sheet.ConditionalFormatting[1].type | should be 'GreaterThan'
|
||||
$sheet.ConditionalFormatting[1].Formula | should be '104857600'
|
||||
$sheet.ConditionalFormatting[1].Style.Font.Color.Color.Name | should be 'ffff0000'
|
||||
}
|
||||
it "Froze the panes" {
|
||||
$sheet.view.Panes.Count | should be 3
|
||||
}
|
||||
$ptsheet1 = $Excel.Workbook.Worksheets["Pt_procs"]
|
||||
|
||||
it "Created the pivot table" {
|
||||
$ptsheet1 | should not beNullOrEmpty
|
||||
$ptsheet1.PivotTables[0].DataFields[0].Field.Name | should be "Name"
|
||||
$ptsheet1.PivotTables[0].DataFields[0].Function | should be "Count"
|
||||
$ptsheet1.PivotTables[0].RowFields[0].Name | should be "Company"
|
||||
$ptsheet1.PivotTables[0].CacheDefinition.CacheDefinitionXml.pivotCacheDefinition.cacheSource.worksheetSource.ref |
|
||||
Should be $sheet.Dimension.address
|
||||
}
|
||||
}
|
||||
|
||||
## To do
|
||||
## More pivot options & other FreezePanes settings ?
|
||||
## Charts
|
||||
## Style script block
|
||||
## Rezip ?
|
||||
|
||||
}
|
||||
|
||||
1110
Export-Excel.ps1
1110
Export-Excel.ps1
File diff suppressed because it is too large
Load Diff
@@ -20,6 +20,7 @@
|
||||
. $PSScriptRoot\Import-Html.ps1
|
||||
. $PSScriptRoot\InferData.ps1
|
||||
. $PSScriptRoot\Invoke-Sum.ps1
|
||||
. $PSScriptRoot\Join-WorkSheet.ps1
|
||||
. $PSScriptRoot\Merge-Worksheet.ps1
|
||||
. $PSScriptRoot\New-ConditionalFormattingIconSet.ps1
|
||||
. $PSScriptRoot\New-ConditionalText.ps1
|
||||
@@ -53,7 +54,7 @@
|
||||
Write-Warning 'PowerShell Excel is ready, except for that functionality'
|
||||
}
|
||||
#endregion
|
||||
Function Import-Excel {
|
||||
function Import-Excel {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Create custom objects from the rows in an Excel worksheet.
|
||||
@@ -92,7 +93,13 @@ Function Import-Excel {
|
||||
When the parameters ‘-NoHeader’ and ‘-HeaderName’ are not provided, this row will contain the column headers that will be used as property names. When one of both parameters are provided, the property names are automatically created and this row will be treated as a regular row containing data.
|
||||
|
||||
.PARAMETER EndRow
|
||||
By default all rows up to the last cell in the sheet will be imported. If specified, import stops at this row.
|
||||
By default all rows up to the last cell in the sheet will be imported. If specified, import stops at this row.
|
||||
|
||||
.PARAMETER StartColumn
|
||||
The number of the first column to read data from (1 by default).
|
||||
|
||||
.PARAMETER EndColumn
|
||||
By default the import reads up to the last populated column, -EndColumn tells the import to stop at an earlier number.
|
||||
|
||||
.PARAMETER Password
|
||||
Accepts a string that will be used to open a password protected Excel file.
|
||||
@@ -318,12 +325,12 @@ Function Import-Excel {
|
||||
#region Open file
|
||||
$Path = (Resolve-Path $Path).ProviderPath
|
||||
Write-Verbose "Import Excel workbook '$Path' with worksheet '$Worksheetname'"
|
||||
|
||||
|
||||
$Stream = New-Object -TypeName System.IO.FileStream -ArgumentList $Path, 'Open', 'Read', 'ReadWrite'
|
||||
|
||||
|
||||
if ($Password) {
|
||||
$Excel = New-Object -TypeName OfficeOpenXml.ExcelPackage
|
||||
|
||||
|
||||
Try {
|
||||
$Excel.Load($Stream,$Password)
|
||||
}
|
||||
@@ -335,7 +342,7 @@ Function Import-Excel {
|
||||
$Excel = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $Stream
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Select worksheet
|
||||
if ($WorksheetName) {
|
||||
if (-not ($Worksheet = $Excel.Workbook.Worksheets[$WorkSheetName])) {
|
||||
@@ -359,7 +366,7 @@ Function Import-Excel {
|
||||
#We're going to look at every cell and build 2 hash tables holding rows & columns which contain data.
|
||||
#Want to Avoid 'select unique' operations & large Sorts, becuse time time taken increases with square
|
||||
#of number of items (PS uses heapsort at large size). Instead keep a list of what we have seen,
|
||||
#using Hash tables: "we've seen it" is all we need, no need to worry about "seen it before" / "Seen it many times"
|
||||
#using Hash tables: "we've seen it" is all we need, no need to worry about "seen it before" / "Seen it many times".
|
||||
$colHash = @{}
|
||||
$rowHash = @{}
|
||||
foreach ($cell in $Worksheet.Cells[$range]) {
|
||||
@@ -415,39 +422,18 @@ Function Import-Excel {
|
||||
}
|
||||
}
|
||||
|
||||
function Add-WorkSheet {
|
||||
param(
|
||||
#TODO Use parametersets to allow a workbook to be passed instead of a package
|
||||
[Parameter(Mandatory=$true, ValueFromPipeline=$true)]
|
||||
[OfficeOpenXml.ExcelPackage] $ExcelPackage,
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string] $WorkSheetname,
|
||||
[switch] $ClearSheet,
|
||||
[Switch] $NoClobber
|
||||
)
|
||||
|
||||
$ws = $ExcelPackage.Workbook.Worksheets[$WorkSheetname]
|
||||
if($ClearSheet -and $ws) {$ExcelPackage.Workbook.Worksheets.Delete($WorkSheetname) ; $ws = $null }
|
||||
if(!$ws) {
|
||||
Write-Verbose "Add worksheet '$WorkSheetname'"
|
||||
$ws=$ExcelPackage.Workbook.Worksheets.Add($WorkSheetname)
|
||||
}
|
||||
|
||||
return $ws
|
||||
}
|
||||
|
||||
function ConvertFrom-ExcelSheet {
|
||||
<#
|
||||
.Synopsis
|
||||
Reads an Excel file an converts the data to a delimited text file
|
||||
.Synopsis
|
||||
Reads an Excel file an converts the data to a delimited text file.
|
||||
|
||||
.Example
|
||||
.Example
|
||||
ConvertFrom-ExcelSheet .\TestSheets.xlsx .\data
|
||||
Reads each sheet in TestSheets.xlsx and outputs it to the data directory as the sheet name with the extension .txt
|
||||
Reads each sheet in TestSheets.xlsx and outputs it to the data directory as the sheet name with the extension .txt.
|
||||
|
||||
.Example
|
||||
.Example
|
||||
ConvertFrom-ExcelSheet .\TestSheets.xlsx .\data sheet?0
|
||||
Reads and outputs sheets like Sheet10 and Sheet20 form TestSheets.xlsx and outputs it to the data directory as the sheet name with the extension .txt
|
||||
Reads and outputs sheets like Sheet10 and Sheet20 form TestSheets.xlsx and outputs it to the data directory as the sheet name with the extension .txt.
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
@@ -496,7 +482,7 @@ function ConvertFrom-ExcelSheet {
|
||||
|
||||
$stream.Close()
|
||||
$stream.Dispose()
|
||||
$xl.Dispose()
|
||||
$xl.Dispose()
|
||||
}
|
||||
|
||||
function Export-MultipleExcelSheets {
|
||||
|
||||
164
Join-Worksheet.ps1
Normal file
164
Join-Worksheet.ps1
Normal file
@@ -0,0 +1,164 @@
|
||||
function Join-Worksheet {
|
||||
[CmdletBinding(DefaultParameterSetName = 'Default')]
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Combines data on all the sheets in an Excel worksheet onto a single sheet.
|
||||
.DESCRIPTION
|
||||
Join worksheet can work in two main ways:
|
||||
Either Combining data which has the same layout from many pages into one, or combining pages which have nothing in common.
|
||||
In the former case the header row is copied from the first sheet and, by default, each row of data is labelled with the name of the sheet it came from.
|
||||
In the latter case -NoHeader is specified, and each copied block can have the sheet it came from placed above it as a title.
|
||||
.EXAMPLE
|
||||
foreach ($computerName in @('Server1', 'Server2', 'Server3', 'Server4')) {
|
||||
Get-Service -ComputerName $computerName | Select-Object -Property Status, Name, DisplayName, StartType |
|
||||
Export-Excel -Path .\test.xlsx -WorkSheetname $computerName -AutoSize
|
||||
}
|
||||
$ptDef =New-PivotTableDefinition -PivotTableName "Pivot1" -SourceWorkSheet "Combined" -PivotRows "Status" -PivotFilter "MachineName" -PivotData @{Status='Count'} -IncludePivotChart -ChartType BarClustered3D
|
||||
Join-Worksheet -Path .\test.xlsx -WorkSheetName combined -FromLabel "MachineName" -HideSource -AutoSize -FreezeTopRow -BoldTopRow -PivotTableDefinition $pt -Show
|
||||
|
||||
The foreach command gets the services running on four servers and exports each to its own page in Test.xlsx.
|
||||
$PtDef= creates a defintion for a single Pivot table.
|
||||
The Join-Worksheet command uses the same file and merges the results onto a sheet named "Combined". It sets a column header of "Machinename",
|
||||
this column will contain the name of the sheet the data was copied from; after copying the data to the sheet "combined", the other sheets will be hidden.
|
||||
Join-Worksheet finishes by calling export-Excel to AutoSize cells, freeze the top row and make it bold and add the Pivot table.
|
||||
|
||||
.EXAMPLE
|
||||
Get-WmiObject -Class win32_logicaldisk | select -Property DeviceId,VolumeName, Size,Freespace |
|
||||
Export-Excel -Path "$env:computerName.xlsx" -WorkSheetname Volumes
|
||||
Get-NetAdapter | Select-Object Name,InterfaceDescription,MacAddress,LinkSpeed |
|
||||
Export-Excel -Path "$env:COMPUTERNAME.xlsx" -WorkSheetname NetAdapter
|
||||
Join-Worksheet -Path "$env:COMPUTERNAME.xlsx" -WorkSheetName Summay -Title "Summary" -TitleBold -TitleSize 22 -NoHeader -LabelBlocks -AutoSize -HideSource
|
||||
|
||||
The first two command get logical disk and network card information; each type is exported to its own sheet in a workbook.
|
||||
The Join-worksheet command copies both onto a page named "Summary". Because the data is disimilar -NoHeader is specified, ensuring the whole of each page is copied.
|
||||
Specifying -LabelBlocks causes each sheet's name to become a title on the summary page above the copied data.
|
||||
The source data is hidden, a title is addded in 22 point boldface and the columns are sized to fit the data.
|
||||
#>
|
||||
param (
|
||||
# Path to a new or existing .XLSX file.
|
||||
[Parameter(ParameterSetName = "Default", Position = 0)]
|
||||
[String]$Path ,
|
||||
# An object representing an Excel Package - usually this is returned by specifying -Passthru allowing multiple commands to work on the same Workbook without saving and reloading each time.
|
||||
[Parameter(Mandatory = $true, ParameterSetName = "Package")]
|
||||
[OfficeOpenXml.ExcelPackage]$ExcelPackage,
|
||||
# The name of a sheet within the workbook where the other sheets will be joined together - "Combined" by default.
|
||||
$WorkSheetName = 'Combined',
|
||||
# If specified any pre-existing target for the joined data will be deleted and re-created; otherwise data will be appended on this sheet.
|
||||
[switch]$Clearsheet,
|
||||
#Join-Worksheet assumes each sheet has identical headers and the headers should be copied to the target sheet, unless -NoHeader is specified.
|
||||
[switch]$NoHeader,
|
||||
#If -NoHeader is NOT specified, then rows of data will be labeled with the name of the sheet they came, FromLabel is the header for this column. If it is null or empty, the labels will be omitted.
|
||||
$FromLabel = "From" ,
|
||||
#If specified, the copied blocks of data will have the name of the sheet they were copied from inserted above them as a title.
|
||||
[switch]$LabelBlocks,
|
||||
#Sizes the width of the Excel column to the maximum width needed to display all the containing data in that cell.
|
||||
[Switch]$AutoSize,
|
||||
#Freezes headers etc. in the top row.
|
||||
[Switch]$FreezeTopRow,
|
||||
#Freezes titles etc. in the left column.
|
||||
[Switch]$FreezeFirstColumn,
|
||||
#Freezes top row and left column (equivalent to Freeze pane 2,2 ).
|
||||
[Switch]$FreezeTopRowFirstColumn,
|
||||
# Freezes panes at specified coordinates (in the form RowNumber , ColumnNumber).
|
||||
[Int[]]$FreezePane,
|
||||
#Enables the 'Filter' in Excel on the complete header row. So users can easily sort, filter and/or search the data in the select column from within Excel.
|
||||
[Switch]$AutoFilter,
|
||||
#Makes the top Row boldface.
|
||||
[Switch]$BoldTopRow,
|
||||
#If Specified hides the sheets that the data is copied from.
|
||||
[switch]$HideSource,
|
||||
#Text of a title to be placed in Cell A1.
|
||||
[String]$Title,
|
||||
#Sets the fill pattern for the title cell.
|
||||
[OfficeOpenXml.Style.ExcelFillStyle]$TitleFillPattern = 'None',
|
||||
#Sets the cell background color for the title cell.
|
||||
[System.Drawing.Color]$TitleBackgroundColor,
|
||||
#Sets the title in boldface type.
|
||||
[Switch]$TitleBold,
|
||||
#Sets the point size for the title.
|
||||
[Int]$TitleSize = 22,
|
||||
# Hashtable(s) with Sheet PivotRows, PivotColumns, PivotData, IncludePivotChart and ChartType values to specify a definition for one or more pivot table(s).
|
||||
[Hashtable]$PivotTableDefinition,
|
||||
# A hashtable containing ChartType, Title, NoLegend, ShowCategory, ShowPercent, Yrange, Xrange and SeriesHeader for one or more [non-pivot] charts.
|
||||
[Object[]]$ExcelChartDefinition,
|
||||
#Opens the Excel file immediately after creation. Convenient for viewing the results instantly without having to search for the file first.
|
||||
[switch]$Show,
|
||||
#If specified, an object representing the unsaved Excel package will be returned, it then needs to be saved.
|
||||
[switch]$PassThru
|
||||
)
|
||||
#region get target worksheet, select it and move it to the end.
|
||||
if ($Path -and -not $ExcelPackage) {$ExcelPackage = Open-ExcelPackage -path $Path }
|
||||
$destinationSheet = Add-WorkSheet -ExcelPackage $ExcelPackage -WorkSheetname $WorkSheetName -ClearSheet:$Clearsheet
|
||||
$destinationSheet.View.TabSelected = $true
|
||||
$ExcelPackage.Workbook.Worksheets.MoveToEnd($WorkSheetName)
|
||||
#row to insert at will be 1 on a blank sheet and lastrow + 1 on populated one
|
||||
$row = (1 + $destinationSheet.Dimension.End.Row )
|
||||
#endregion
|
||||
|
||||
#region Setup title and header rows
|
||||
#Title parameters work as they do in Export-Excel .
|
||||
if ($row -eq 1 -and $Title) {
|
||||
$destinationSheet.Cells[1, 1].Value = $Title
|
||||
$destinationSheet.Cells[1, 1].Style.Font.Size = $TitleSize
|
||||
if ($TitleBold) {$destinationSheet.Cells[1, 1].Style.Font.Bold = $True }
|
||||
#Can only set TitleBackgroundColor if TitleFillPattern is something other than None.
|
||||
if ($TitleBackgroundColor -AND ($TitleFillPattern -ne 'None')) {
|
||||
$destinationSheet.Cells[1, 1].Style.Fill.PatternType = $TitleFillPattern
|
||||
$destinationSheet.Cells[1, 1].Style.Fill.BackgroundColor.SetColor($TitleBackgroundColor)
|
||||
}
|
||||
elseif ($TitleBackgroundColor) { Write-Warning "Title Background Color ignored. You must set the TitleFillPattern parameter to a value other than 'None'. Try 'Solid'." }
|
||||
$row = 2
|
||||
}
|
||||
|
||||
if (-not $noHeader) {
|
||||
#Assume every row has titles in row 1, copy row 1 from first sheet to new sheet.
|
||||
$destinationSheet.Select("A$row")
|
||||
$ExcelPackage.Workbook.Worksheets[1].cells["1:1"].Copy($destinationSheet.SelectedRange)
|
||||
if ($FromLabel ) {
|
||||
#Add a column which says where the data comes from.
|
||||
$fromColumn = ($destinationSheet.Dimension.Columns + 1)
|
||||
$destinationSheet.Cells[$row, $fromColumn].Value = $FromLabel
|
||||
}
|
||||
$row += 1
|
||||
}
|
||||
#endregion
|
||||
|
||||
foreach ($i in 1..($ExcelPackage.Workbook.Worksheets.Count - 1) ) {
|
||||
$sourceWorksheet = $ExcelPackage.Workbook.Worksheets[$i]
|
||||
#Assume row one is titles, so data itself starts at A2.
|
||||
if ($NoHeader) {$sourceRange = $sourceWorksheet.Dimension.Address}
|
||||
else {$sourceRange = $sourceWorksheet.Dimension.Address -replace "A1:", "A2:"}
|
||||
#Position insertion point/
|
||||
$destinationSheet.Select("A$row")
|
||||
if ($LabelBlocks) {
|
||||
$destinationSheet.Cells[$row, 1].value = $sourceWorksheet.Name
|
||||
$destinationSheet.Cells[$row, 1].Style.Font.Bold = $true
|
||||
$destinationSheet.Cells[$row, 1].Style.Font.Size += 2
|
||||
$row += 1
|
||||
}
|
||||
$destinationSheet.Select("A$row")
|
||||
|
||||
#And finally we're ready to copy the data.
|
||||
$sourceWorksheet.Cells[$sourceRange].Copy($destinationSheet.SelectedRange)
|
||||
#Fill in column saying where data came from.
|
||||
if ($fromColumn) { $row..$destinationSheet.Dimension.Rows | ForEach-Object {$destinationSheet.Cells[$_, $fromColumn].Value = $sourceWorksheet.Name} }
|
||||
#Update where next insertion will go.
|
||||
$row = $destinationSheet.Dimension.Rows + 1
|
||||
if ($HideSource) {$sourceWorksheet.Hidden = [OfficeOpenXml.eWorkSheetHidden]::Hidden}
|
||||
}
|
||||
|
||||
#We accept a bunch of parameters work to pass on to Export-excel ( Autosize, Autofilter, boldtopRow Freeze ); if we have any of those call export-excel otherwise close the package here.
|
||||
$params = @{} + $PSBoundParameters
|
||||
'Path', 'Clearsheet', 'NoHeader', 'FromLabel', 'LabelBlocks', 'HideSource',
|
||||
'Title', 'TitleFillPattern', 'TitleBackgroundColor', 'TitleBold', 'TitleSize' | ForEach-Object {[void]$params.Remove($_)}
|
||||
if ($params.Keys.Count) {
|
||||
$params.WorkSheetName = $WorkSheetName
|
||||
$params.ExcelPackage = $ExcelPackage
|
||||
Export-Excel @Params
|
||||
}
|
||||
else {
|
||||
Close-ExcelPackage -ExcelPackage $ExcelPackage
|
||||
$ExcelPackage.Dispose()
|
||||
$ExcelPackage = $null
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
.Example
|
||||
merge-worksheet "Server54.xlsx" "Server55.xlsx" -WorkSheetName services -OutputFile Services.xlsx -OutputSheetName 54-55 -show
|
||||
The workbooks contain audit information for two servers, one page contains a list of services. This command creates a worksheet named 54-55
|
||||
in a workbook named services which shows all the services and their differences, and opens it in Excel
|
||||
in a workbook named services which shows all the services and their differences, and opens it in Excel.
|
||||
.Example
|
||||
merge-worksheet "Server54.xlsx" "Server55.xlsx" -WorkSheetName services -OutputFile Services.xlsx -OutputSheetName 54-55 -HideEqual -AddBackgroundColor LightBlue -show
|
||||
This modifies the previous command to hide the equal rows in the output sheet and changes the color used to mark rows added to the second file.
|
||||
@@ -17,12 +17,12 @@
|
||||
merge-worksheet -OutputFile .\j1.xlsx -OutputSheetName test11 -ReferenceObject (dir .\ImportExcel\4.0.7) -DifferenceObject (dir .\ImportExcel\4.0.8) -Property Length -Show
|
||||
This version compares two directories, and marks what has changed.
|
||||
Because no "Key" property is given, "Name" is assumed to be the key and the only other property examined is length.
|
||||
Files which are added or deleted or have changed size will be highlighed in the output sheet. Changes to dates or other attributes will be ignored
|
||||
Files which are added or deleted or have changed size will be highlighed in the output sheet. Changes to dates or other attributes will be ignored.
|
||||
.Example
|
||||
merge-worksheet -RefO (dir .\ImportExcel\4.0.7) -DiffO (dir .\ImportExcel\4.0.8) -Pr Length | Out-GridView
|
||||
This time no file is written and the results -which include all properties, not just length, are output and sent to Out-Gridview.
|
||||
This version uses aliases to shorten the parameters,
|
||||
(OutputFileName can be "outFile" and the sheet "OutSheet" : DifferenceObject & ReferenceObject can be DiffObject & RefObject)
|
||||
(OutputFileName can be "outFile" and the sheet "OutSheet" : DifferenceObject & ReferenceObject can be DiffObject & RefObject).
|
||||
#>
|
||||
[cmdletbinding(SupportsShouldProcess=$true)]
|
||||
Param(
|
||||
@@ -60,11 +60,13 @@
|
||||
#Automatically generate property names (P1, P2, P3, ..) instead of the using the values the top row of the sheet.
|
||||
[Parameter(ParameterSetName='C',Mandatory=$true)]
|
||||
[switch]$NoHeader,
|
||||
|
||||
|
||||
#Object to compare if a worksheet is NOT being used.
|
||||
[parameter(ParameterSetName='D',Mandatory=$true)]
|
||||
[parameter(ParameterSetName='E',Mandatory=$true)]
|
||||
[Alias('RefObject')]
|
||||
$ReferenceObject ,
|
||||
#Object to compare if a worksheet is NOT being used.
|
||||
[parameter(ParameterSetName='D',Mandatory=$true,Position=1)]
|
||||
[Alias('DiffObject')]
|
||||
$DifferenceObject ,
|
||||
@@ -95,7 +97,7 @@
|
||||
[System.Drawing.Color]$AddBackgroundColor = "PaleGreen",
|
||||
#if Specified hides the rows in the spreadsheet that are equal and only shows changes, added or deleted rows.
|
||||
[switch]$HideEqual ,
|
||||
#If specified outputs the data to the pipeline (you can add -whatif so it the command only outputs to the command)
|
||||
#If specified outputs the data to the pipeline (you can add -whatif so it the command only outputs to the pipeline).
|
||||
[switch]$Passthru ,
|
||||
#If specified, opens the output workbook.
|
||||
[Switch]$Show
|
||||
@@ -238,10 +240,10 @@
|
||||
[Pscustomobject]$hash
|
||||
} | Sort-Object -Property "_row"
|
||||
|
||||
#Already sorted by reference row number, fill in any blanks in the difference-row column
|
||||
#Already sorted by reference row number, fill in any blanks in the difference-row column.
|
||||
for ($i = 1; $i -lt $expandedDiff.Count; $i++) {if (-not $expandedDiff[$i]."$DiffPrefix Row") {$expandedDiff[$i]."$DiffPrefix Row" = $expandedDiff[$i-1]."$DiffPrefix Row" } }
|
||||
|
||||
#Now re-Sort by difference row number, and fill in any blanks in the reference-row column
|
||||
#Now re-Sort by difference row number, and fill in any blanks in the reference-row column.
|
||||
$expandedDiff = $expandedDiff | Sort-Object -Property "$DiffPrefix Row"
|
||||
for ($i = 1; $i -lt $expandedDiff.Count; $i++) {if (-not $expandedDiff[$i]."_Row") {$expandedDiff[$i]."_Row" = $expandedDiff[$i-1]."_Row" } }
|
||||
|
||||
@@ -278,27 +280,30 @@
|
||||
}
|
||||
}
|
||||
|
||||
Function Merge-MulipleSheets {
|
||||
<#
|
||||
Function Merge-MultipleSheets {
|
||||
<#
|
||||
.Synopsis
|
||||
Merges worksheets into a single worksheet with differences marked up.
|
||||
.Description
|
||||
The Merge worksheet command combines 2 sheets. Merge-MultipleSheets is designed to merge more than 2.
|
||||
So if asked to merge sheets A,B,C which contain Services, with a Name, Displayname and Start mode, where "name" is treated as the key
|
||||
it calls Merge-Worksheet to merge Name, Displayname and Start mode,from sheets A and C the result has column headings
|
||||
-Row, Name, DisplayName, Startmode, C-DisplayName, C-StartMode C-Is, C-Row
|
||||
Then it calls merge-worsheet with this result and sheet B, comparing 'Name', 'Displayname' and 'Start mode' columns on each side and outputting
|
||||
_Row, Name, DisplayName, Startmode, B-DisplayName, B-StartMode B-Is, B-Row, C-DisplayName, C-StartMode C-Is, C-Row
|
||||
Any columns in the "reference" side which are not used in the comparison are appended on the right, which is we compare the sheets in reverse order
|
||||
Merge-MultipleSheets calls Merge-Worksheet to merge Name, Displayname and Start mode, from sheets A and C
|
||||
the result has column headings -Row, Name, DisplayName, Startmode, C-DisplayName, C-StartMode C-Is, C-Row
|
||||
Merge-MultipleSheets then calls Merge-Worsheet with this result and sheet B, comparing 'Name', 'Displayname' and 'Start mode' columns on each side
|
||||
which outputs _Row, Name, DisplayName, Startmode, B-DisplayName, B-StartMode B-Is, B-Row, C-DisplayName, C-StartMode C-Is, C-Row
|
||||
Any columns in the "reference" side which are not used in the comparison are appended on the right, which is we compare the sheets in reverse order.
|
||||
|
||||
The "Is" column holds "Same", "Added", "Removed" or "Changed" and is used for conditional formatting in the output sheet (this is hidden by default),
|
||||
and when the data is written to Excel the "reference" columns "DisplayName" and "Start" are renamed "A-DisplayName" and "A-Start"
|
||||
and when the data is written to Excel the "reference" columns, in this case "DisplayName" and "Start" are renamed to reflect their source,
|
||||
so become "A-DisplayName" and "A-Start".
|
||||
|
||||
Conditional formatting is also applied to the "key" column (name in this case) so the view can be filtered to rows with changes by filtering this column on color.
|
||||
|
||||
Note: the processing order can affect what is seen as a change. For example if there is an extra item in sheet B in the example above,
|
||||
Sheet C will be processed and that row and nothing will be seen to be missing. When sheet B is processed it is marked as an addition, and the conditional formatting marks
|
||||
Sheet C will be processed and that row and will not be seen to be missing. When sheet B is processed it is marked as an addition, and the conditional formatting marks
|
||||
the entries from sheet A to show that a values were added in at least one sheet.
|
||||
However of Sheet B is the reference sheet, A and C will be seen to have an item removed; and if B is processed before C, the extra item is known when C is processed and
|
||||
so C is considered to be missing that item.
|
||||
However if Sheet B is the reference sheet, A and C will be seen to have an item removed;
|
||||
and if B is processed before C, the extra item is known when C is processed and so C is considered to be missing that item.
|
||||
.Example
|
||||
dir Server*.xlsx | Merge-MulipleSheets -WorkSheetName Services -OutputFile Test2.xlsx -OutputSheetName Services -Show
|
||||
We are auditing servers and each one has a workbook in the current directory which contains a "Services" worksheet (the result of
|
||||
@@ -313,7 +318,7 @@ Function Merge-MulipleSheets {
|
||||
This time all the servers have written their hofix information to their own worksheets in a shared Excel workbook named "Hotfixes"
|
||||
(the information was obtained by running Get-Hotfix | Sort-Object -Property description,hotfixid | Select-Object -Property Description,HotfixID)
|
||||
This ignores any sheets which are not named "Serv*", and uses the HotfixID as the key ; in this version the row numbers are hidden.
|
||||
#>
|
||||
#>
|
||||
|
||||
param (
|
||||
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
|
||||
|
||||
94
Old_Export-Excel.Tests.ps1
Normal file
94
Old_Export-Excel.Tests.ps1
Normal file
@@ -0,0 +1,94 @@
|
||||
#Requires -Modules Pester
|
||||
|
||||
|
||||
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
|
||||
|
||||
Import-Module $here -Force
|
||||
|
||||
$WarningPreference = 'SilentlyContinue'
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
|
||||
Function Test-isNumeric {
|
||||
Param (
|
||||
[Parameter(ValueFromPipeline)]$x
|
||||
)
|
||||
|
||||
Return $x -is [byte] -or $x -is [int16] -or $x -is [int32] -or $x -is [int64] `
|
||||
-or $x -is [sbyte] -or $x -is [uint16] -or $x -is [uint32] -or $x -is [uint64] `
|
||||
-or $x -is [float] -or $x -is [double] -or $x -is [decimal]
|
||||
}
|
||||
|
||||
$fakeData = [PSCustOmobject]@{
|
||||
Property_1_Date = (Get-Date).ToString('d') # US '10/16/2017' BE '16/10/2107'
|
||||
Property_2_Formula = '=SUM(G2:H2)'
|
||||
Property_3_String = 'My String'
|
||||
Property_4_String = 'a'
|
||||
Property_5_IPAddress = '10.10.25.5'
|
||||
Property_6_Number = '0'
|
||||
Property_7_Number = '5'
|
||||
Property_8_Number = '007'
|
||||
Property_9_Number = (33).ToString('F2') # US '33.00' BE '33,00'
|
||||
Property_10_Number = (5/3).ToString('F2') # US '1.67' BE '1,67'
|
||||
Property_11_Number = (15999998/3).ToString('N2') # US '5,333,332.67' BE '5.333.332,67'
|
||||
Property_12_Number = '1.555,83'
|
||||
Property_13_PhoneNr = '+32 44'
|
||||
Property_14_PhoneNr = '+32 4 4444 444'
|
||||
Property_15_PhoneNr = '+3244444444'
|
||||
}
|
||||
|
||||
$Path = 'Test.xlsx'
|
||||
|
||||
Describe 'Export-Excel' {
|
||||
in $TestDrive {
|
||||
Describe 'Number conversion' {
|
||||
Context 'numerical values expected' {
|
||||
#region Create test file
|
||||
$fakeData | Export-Excel -Path $Path
|
||||
|
||||
$Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path)
|
||||
$Excel = New-Object OfficeOpenXml.ExcelPackage $Path
|
||||
$Worksheet = $Excel.Workbook.WorkSheets[1]
|
||||
#endregion
|
||||
|
||||
it 'zero' {
|
||||
$fakeData.Property_6_Number | Should -BeExactly '0'
|
||||
$Worksheet.Cells[2, 6].Text | Should -BeExactly $fakeData.Property_6_Number
|
||||
$Worksheet.Cells[2, 6].Value | Test-isNumeric | Should -Be $true
|
||||
}
|
||||
|
||||
It 'regular number' {
|
||||
$fakeData.Property_7_Number | Should -BeExactly '5'
|
||||
$Worksheet.Cells[2, 7].Text | Should -BeExactly $fakeData.Property_7_Number
|
||||
$Worksheet.Cells[2, 7].Value | Test-isNumeric | Should -Be $true
|
||||
}
|
||||
|
||||
It 'number starting with zero' {
|
||||
$fakeData.Property_8_Number | Should -BeExactly '007'
|
||||
$Worksheet.Cells[2, 8].Text | Should -BeExactly '7'
|
||||
$Worksheet.Cells[2, 8].Value | Test-isNumeric | Should -Be $true
|
||||
}
|
||||
|
||||
It 'decimal number' {
|
||||
# US '33.00' BE '33,00'
|
||||
$fakeData.Property_9_Number | Should -BeExactly (33).ToString('F2')
|
||||
$Worksheet.Cells[2, 9].Text | Should -BeExactly '33'
|
||||
$Worksheet.Cells[2, 9].Value | Test-isNumeric | Should -Be $true
|
||||
|
||||
# US '1.67' BE '1,67'
|
||||
$fakeData.Property_10_Number | Should -BeExactly (5/3).ToString('F2')
|
||||
$Worksheet.Cells[2, 10].Text | Should -BeExactly $fakeData.Property_10_Number
|
||||
$Worksheet.Cells[2, 10].Value | Test-isNumeric | Should -Be $true
|
||||
}
|
||||
|
||||
It 'thousand seperator and decimal number' {
|
||||
# US '5,333,332.67' BE '5.333.332,67'
|
||||
# Excel BE '5333332,67'
|
||||
$fakeData.Property_11_Number | Should -BeExactly (15999998/3).ToString('N2')
|
||||
$Worksheet.Cells[2, 11].Text | Should -BeExactly $fakeData.Property_11_Number
|
||||
$Worksheet.Cells[2, 11].Value | Test-isNumeric | Should -Be $true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,39 +5,55 @@
|
||||
.Example
|
||||
$excel = Open-ExcelPackage -path $xlPath
|
||||
$sheet1 = $excel.Workbook.Worksheets["sheet1"]
|
||||
set-Format -Address $sheet1.Cells["E1:S1048576"], $sheet1.Cells["V1:V1048576"] -NFormat ([cultureinfo]::CurrentCulture.DateTimeFormat.ShortDatePattern)
|
||||
close-ExcelPackage $excel -Show
|
||||
Set-Format -Address $sheet1.Cells["E1:S1048576"], $sheet1.Cells["V1:V1048576"] -NFormat ([cultureinfo]::CurrentCulture.DateTimeFormat.ShortDatePattern)
|
||||
Close-ExcelPackage $excel -Show
|
||||
|
||||
This will open the file at $xlPath, select sheet1 apply formatting to two blocks of the sheet and close the package
|
||||
This will open the file at $xlPath, select sheet1 apply formatting to two blocks of the sheet and save the package, and launch it in Excel.
|
||||
#>
|
||||
[OutputType([OfficeOpenXml.ExcelPackage])]
|
||||
Param ([Parameter(Mandatory=$true)]$Path,
|
||||
[switch]$KillExcel)
|
||||
Param (
|
||||
#The Path to the file to open
|
||||
[Parameter(Mandatory=$true)]$Path,
|
||||
#If specified, any running instances of Excel will be terminated before opening the file.
|
||||
[switch]$KillExcel,
|
||||
#By default open only opens an existing file; -Create instructs it to create a new file if required.
|
||||
[switch]$Create
|
||||
)
|
||||
|
||||
if($KillExcel) {
|
||||
Get-Process -Name "excel" -ErrorAction Ignore | Stop-Process
|
||||
while (Get-Process -Name "excel" -ErrorAction Ignore) {}
|
||||
if($KillExcel) {
|
||||
Get-Process -Name "excel" -ErrorAction Ignore | Stop-Process
|
||||
while (Get-Process -Name "excel" -ErrorAction Ignore) {}
|
||||
}
|
||||
|
||||
$Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path)
|
||||
#If -Create was not specified only open the file if it exists already (send a warning if it doesn't exist).
|
||||
if ($Create) {
|
||||
#Create the directory if required.
|
||||
$targetPath = Split-Path -Parent -Path $Path
|
||||
if (!(Test-Path -Path $targetPath)) {
|
||||
Write-Debug "Base path $($targetPath) does not exist, creating"
|
||||
$null = New-item -ItemType Directory -Path $targetPath -ErrorAction Ignore
|
||||
}
|
||||
|
||||
$Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path)
|
||||
if (Test-Path $path) {New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $Path }
|
||||
Else {Write-Warning "Could not find $path" }
|
||||
New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $Path
|
||||
}
|
||||
elseif (Test-Path -Path $path) {New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $Path }
|
||||
else {Write-Warning "Could not find $path" }
|
||||
}
|
||||
|
||||
Function Close-ExcelPackage {
|
||||
<#
|
||||
.Synopsis
|
||||
Closes an Excel Package, saving, saving under a new name or abandoning changes and opening the file as required
|
||||
Closes an Excel Package, saving, saving under a new name or abandoning changes and opening the file in Excel as required.
|
||||
#>
|
||||
Param (
|
||||
#File to close
|
||||
#File to close.
|
||||
[parameter(Mandatory=$true, ValueFromPipeline=$true)]
|
||||
[OfficeOpenXml.ExcelPackage]$ExcelPackage,
|
||||
#Open the file
|
||||
#Open the file.
|
||||
[switch]$Show,
|
||||
#Abandon the file without saving
|
||||
#Abandon the file without saving.
|
||||
[Switch]$NoSave,
|
||||
#Save file with a new name (ignored if -NoSaveSpecified)
|
||||
#Save file with a new name (ignored if -NoSave Specified).
|
||||
$SaveAs
|
||||
)
|
||||
if ( $NoSave) {$ExcelPackage.Dispose()}
|
||||
@@ -47,4 +63,5 @@ Function Close-ExcelPackage {
|
||||
$ExcelPackage.Dispose()
|
||||
if ($show) {Start-Process -FilePath $SaveAs }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
74
README.md
74
README.md
@@ -37,39 +37,49 @@ iex (new-object System.Net.WebClient).DownloadString('https://raw.github.com/dfi
|
||||
|
||||
# What's new
|
||||
|
||||
#### 6/26/2018
|
||||
- New commands - Diff , Merge and Join
|
||||
- `Compare-Worksheet` (introduced in 5.0) uses the built in `Compare-object` command, to output a command-line DIFF and/or color the worksheet to show differences. For example, if my sheets are Windows services the *extra* rows or rows where the startup status has changed get highlighted
|
||||
- `Merge-Worksheet` (also introduced in 5.0) joins two lumps, side by highlighting the differences. So now I can have server A's services and Server Bs Services on the same page. I figured out a way to do multiple sheets. So I can have Server A,B,C,D on one page :-) that is `Merge-MultpleSheets`
|
||||
For this release I've fixed heaven only knows how many typos and proof reading errors in the help for these two, but the code is unchanged - although correcting the spelling of Merge-MultipleSheets is potentially a breaking change (and it is still plural!)
|
||||
also fixed a bug in compare worksheet where color might not be applied correctly when the worksheets came from different files and had different name.
|
||||
- `Join-Worksheet` is **new** for this release. At it's simplest it copies all the data in Worksheet A to the end of Worksheet B
|
||||
- Add-Worksheet
|
||||
- I have moved this from ImportExcel.psm1 to ExportExcel.ps1 and it now can move a new worksheet to the right place, and can copy an existing worksheet (from the same or a different workbook) to a new one, and I set the Set return-type to aid intellisense
|
||||
- New-PivotTableDefinition
|
||||
- Now Supports `-PivotFilter` and `-PivotDataToColumn`, `-ChartHeight/width` `-ChartRow/Column`, `-ChartRow/ColumnPixelOffset` parameters
|
||||
- Set-Format
|
||||
- Fixed a bug where the `-address` parameter had to be named, although the examples in `export-excel` help showed it working by position (which works now. )
|
||||
- Export-Excel
|
||||
- I've done some re-factoring
|
||||
1. I "flattened out" small "called-once" functions , add-title, convert-toNumber and Stop-ExcelProcess.
|
||||
2. It now uses Add-Worksheet, Open-ExcelPackage and Add-ConditionalFormat instead of duplicating their functionality.
|
||||
3. I've moved the PivotTable functionality (which was doubled up) out to a new function "Add-PivotTable" which supports some extra parameters PivotFilter and PivotDataToColumn, ChartHeight/width ChartRow/Column, ChartRow/ColumnPixelOffsets.
|
||||
4. I've made the try{} catch{} blocks cover smaller blocks of code to give a better idea where a failure happened, some of these now Warn instead of throwing - I'd rather save the data with warnings than throw it away because we can't add a chart. Along with this I've added some extra write-verbose messages
|
||||
- Bad column-names specified for Pivots now generate warnings instead of throwing.
|
||||
- Fixed issues when pivot tables / charts already exist and an export tries to create them again.
|
||||
- Fixed issue where AutoNamedRange, NamedRange, and TableName do not work when appending to a sheet which already contains the range(s) / table
|
||||
- Fixed issue where AutoNamedRange may try to create ranges with an illegal name.
|
||||
- Added check for illegal characters in RangeName or Table Name (replace them with "_"), changed tablename validation to allow spaces and applied same validation to RangeName
|
||||
- Fixed a bug where BoldTopRow is always bolds row 1 even if the export is told to start at a lower row.
|
||||
- Fixed a bug where titles throw pivot table creation out of alignment.
|
||||
- Fixed a bug where Append can overwrite the last rows of data if the initial export had blank rows at the top of the sheet.
|
||||
- Removed the need to specify a fill type when specifying a title background color
|
||||
- Added MoveToStart, MoveToEnd, MoveBefore and MoveAfter Parameters - these go straight through to Add worksheet
|
||||
- Added "NoScriptOrAliasProperties" "DisplayPropertySet" switches (names subject to change) - combined with ExcludeProperty these are a quick way to reduce the data exported (and speed things up)
|
||||
- Added PivotTableName Switch (in line with 5.0.1 release)
|
||||
- Add-CellValue now understands URI item properties. If a property is of type URI it is created as a hyperlink to speed up Add-CellValue
|
||||
- Commented out the write verbose statements even if verbose is silenced they cause a significant performance impact and if it's on they will cause a flood of messages.
|
||||
- Re-ordered the choices in the switch and added an option to say "If it is numeric already post it as is"
|
||||
- Added an option to only set the number format if doesn't match the default for the sheet.
|
||||
-Export-Excel Pester Tests
|
||||
- I have converted examples 1-9, 11 and 13 from Export-Excel help into tests and have added some additional tests, and extra parameters to the example command to get better test coverage. The test so far has 184 "should" conditions grouped as 58 "IT" statements; but is still a work in progress.
|
||||
-Compare-Worksheet pester tests
|
||||
|
||||
* Added Merge-Worksheet.ps1 so the install and publish will include this
|
||||
* Now allows you to name the pivot table sheet name when using `-IncludePivotTable`
|
||||
* Demo of the `-PivotTableName` parameter
|
||||
* Added `-UseMSSQLSyntax` to code gen INSERT INTO correct format format
|
||||
* Demo of the `-UseMSSQLSyntax` parameter [DemoSQLInsert](Examples/ExcelToSQLInsert/DemoSQLInsert.ps1)
|
||||
---
|
||||
|
||||
#### 06/08/2018
|
||||
Thank you again to [James O'Neill](https://twitter.com/jamesoneill) for the lion share of these updates.
|
||||
Most notably the performance gains in the `Import-Excel` function.
|
||||
|
||||
In addition, I have started to create tests and wired up Appveyor for continuous integration
|
||||
|
||||
This release will be bumped to 5.0.0 and will be published officially after more testing.
|
||||
|
||||
* added databar to Examples
|
||||
* Fix databar example
|
||||
* increased how long the import should take
|
||||
* Renamed test directory
|
||||
* Added PSVersion. Point to the new directory for tests
|
||||
* Added EndRow, StartColumn, EndColumn to Import-Excel
|
||||
* Added Merge-MultipleSheets to argument completers
|
||||
* added build badge
|
||||
* Making Merge-Worksheet, and Merge-MultipleWorksheet ready to release
|
||||
* Added Merge Multiple worksheet
|
||||
* Revert "Added Multiple Merge to Merge-Worksheet.ps1"
|
||||
* Added Multiple Merge to Merge-Worksheet.ps1
|
||||
* Added Merge-worksheet
|
||||
* Force install of pester
|
||||
* Checks version of pester on appveyor
|
||||
* First step to wire up appveyor
|
||||
* 13 days ago : Tidying of case, parameter clarity, removal of aliases. Added timeout to send-SqlDataToExcel Added Merge WorkSheet Fixed bugs in Compare-Worksheet
|
||||
- [James O'Neill](https://twitter.com/jamesoneill) added `Compare-Worksheet`
|
||||
- Compares two worksheets with the same name in different files.
|
||||
|
||||
#### 4/22/2018
|
||||
Thanks to the community yet again
|
||||
@@ -631,7 +641,7 @@ Or
|
||||
#### 9/25/2015
|
||||
|
||||
**Hide worksheets**
|
||||
Got a great request from [forensicsguy20012004](https://github.com/forensicsguy20012004) to hide worksheets. You create a few pivot tables, generate charts and then pivot table worksheets don't need to be visible.
|
||||
Got a great request from [forensicsguy20012004](https://github.com/forensicsguy20012004) to hide worksheets. You create a few pivotables, generate charts and then pivot table worksheets don't need to be visible.
|
||||
|
||||
`Export-Excel` now has a `-HideSheet` parameter that takes and array of worksheet names and hides them.
|
||||
|
||||
@@ -823,4 +833,4 @@ You can also find EPPLus on [Nuget](https://www.nuget.org/packages/EPPlus/).
|
||||
|
||||
* Using `-IncludePivotTable`, if that pivot table name exists, you'll get an error.
|
||||
* Investigating a solution
|
||||
* *Workaround* delete the Excel file first, then do the export
|
||||
* *Workaround* delete the Excel file first, then do the export
|
||||
@@ -12,7 +12,7 @@
|
||||
#>
|
||||
Param (
|
||||
#One or more row(s), Column(s) and/or block(s) of cells to format
|
||||
[Parameter(ValueFromPipeline = $true,ParameterSetName="Address",Mandatory=$True)]
|
||||
[Parameter(ValueFromPipeline = $true,ParameterSetName="Address",Mandatory=$True,Position=0)]
|
||||
$Address ,
|
||||
#The worksheet where the format is to be applied
|
||||
[Parameter(ParameterSetName="SheetAndRange",Mandatory=$True)]
|
||||
|
||||
@@ -1,252 +0,0 @@
|
||||
Function Compare-WorkSheet {
|
||||
<#
|
||||
.Synopsis
|
||||
Compares two worksheets with the same name in different files.
|
||||
.Description
|
||||
This command takes two file names, a worksheet name and a name for a key column.
|
||||
It reads the worksheet from each file and decides the column names.
|
||||
It builds as hashtable of the key column values and the rows they appear in
|
||||
It then uses PowerShell's compare object command to compare the sheets (explicity checking all column names which have not been excluded)
|
||||
For the difference rows it adds the row number for the key of that row - we have to add the key after doing the comparison,
|
||||
otherwise rows will be considered as different simply because they have different row numbers
|
||||
We also add the name of the file in which the difference occurs.
|
||||
If -BackgroundColor is specified the difference rows will be changed to that background.
|
||||
.Example
|
||||
Compare-WorkSheet -Referencefile 'Server56.xlsx' -Differencefile 'Server57.xlsx' -WorkSheetName Products -key IdentifyingNumber -ExcludeProperty Install* | format-table
|
||||
The two workbooks in this example contain the result of redirecting a subset of properties from Get-WmiObject -Class win32_product to Export-Excel
|
||||
The command compares the "products" pages in the two workbooks, but we don't want to register a differnce if if the software was installed on a
|
||||
different date or from a different place, so Excluding Install* removes InstallDate and InstallSource.
|
||||
This data doesn't have a "name" column" so we specify the "IdentifyingNumber" column as the key.
|
||||
The results will be presented as a table.
|
||||
.Example
|
||||
compare-WorkSheet "Server54.xlsx" "Server55.xlsx" -WorkSheetName services -GridView
|
||||
This time two workbooks contain the result of redirecting Get-WmiObject -Class win32_service to Export-Excel
|
||||
Here the -Differencefile and -Referencefile parameter switches are assumed , and the default setting for -key ("Name") works for services
|
||||
This will display the differences between the "services" sheets using a grid view
|
||||
.Example
|
||||
Compare-WorkSheet 'Server54.xlsx' 'Server55.xlsx' -WorkSheetName Services -BackgroundColor lightGreen
|
||||
This version of the command outputs the differences between the "services" pages and also highlights any different rows in the spreadsheet files.
|
||||
.Example
|
||||
Compare-WorkSheet 'Server54.xlsx' 'Server55.xlsx' -WorkSheetName Services -BackgroundColor lightGreen -FontColor Red -Show
|
||||
This builds on the previous example: this time Where two changed rows have the value in the "name" column (the default value for -key),
|
||||
this version adds highlighting of the changed cells in red; and then opens the Excel file.
|
||||
.Example
|
||||
Compare-WorkSheet 'Pester-tests.xlsx' 'Pester-tests.xlsx' -WorkSheetName 'Server1','Server2' -Property "full Description","Executed","Result" -Key "full Description"
|
||||
This time the reference file and the difference file are the same file and two different sheets are used. Because the tests include the
|
||||
machine name and time the test was run the command specifies a limited set of columns should be used.
|
||||
.Example
|
||||
Compare-WorkSheet 'Server54.xlsx' 'Server55.xlsx' -WorkSheetName general -Startrow 2 -Headername Label,value -Key Label -GridView -ExcludeDifferent
|
||||
The "General" page has a title and two unlabelled columns with a row forCPU, Memory, Domain, Disk and so on
|
||||
So the command is instructed to starts at row 2 to skip the title and to name the columns: the first is "label" and the Second "Value";
|
||||
the label acts as the key. This time we interested the rows which are the same in both sheets,
|
||||
and the result is displayed using grid view. Note that grid view works best when the number of columns is small.
|
||||
.Example
|
||||
Compare-WorkSheet 'Server1.xlsx' 'Server2.xlsx' -WorkSheetName general -Startrow 2 -Headername Label,value -Key Label -BackgroundColor White -Show -AllDataBackgroundColor LightGray
|
||||
This version of the previous command lightlights all the cells in lightgray and then sets the changed rows back to white; only
|
||||
the unchanged rows are highlighted
|
||||
#>
|
||||
[cmdletbinding(DefaultParameterSetName)]
|
||||
Param(
|
||||
#First file to compare
|
||||
[parameter(Mandatory=$true,Position=0)]
|
||||
$Referencefile ,
|
||||
#Second file to compare
|
||||
[parameter(Mandatory=$true,Position=1)]
|
||||
$Differencefile ,
|
||||
#Name(s) of worksheets to compare.
|
||||
$WorkSheetName = "Sheet1",
|
||||
#Properties to include in the DIFF - supports wildcards, default is "*"
|
||||
$Property = "*" ,
|
||||
#Properties to exclude from the the search - supports wildcards
|
||||
$ExcludeProperty ,
|
||||
#Specifies custom property names to use, instead of the values defined in the column headers of the TopRow.
|
||||
[Parameter(ParameterSetName='B', Mandatory)]
|
||||
[String[]]$Headername,
|
||||
#Automatically generate property names (P1, P2, P3, ..) instead of the using the values the top row of the sheet
|
||||
[Parameter(ParameterSetName='C', Mandatory)]
|
||||
[switch]$NoHeader,
|
||||
#The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row.
|
||||
[int]$Startrow = 1,
|
||||
#If specified, highlights all the cells - so you can make Equal cells one colour, and Diff cells another.
|
||||
[System.Drawing.Color]$AllDataBackgroundColor,
|
||||
#If specified, highlights the DIFF rows
|
||||
[System.Drawing.Color]$BackgroundColor,
|
||||
#If specified identifies the tabs which contain DIFF rows (ignored if -backgroundColor is omitted)
|
||||
[System.Drawing.Color]$TabColor,
|
||||
#Name of a column which is unique and will be used to add a row to the DIFF object, default is "Name"
|
||||
$Key = "Name" ,
|
||||
#If specified, highlights the DIFF columns in rows which have the same key.
|
||||
[System.Drawing.Color]$FontColor,
|
||||
#If specified opens the Excel workbooks instead of outputting the diff to the console (unless -passthru is also specified)
|
||||
[Switch]$Show,
|
||||
#If specified, the command tries to the show the DIFF in a Gridview and not on the console. (unless-Passthru is also specified). This Works best with few columns selected, and requires a key
|
||||
[switch]$GridView,
|
||||
#If specified -Passthrough full set of diff data is returned without filtering to the specified properties
|
||||
[Switch]$PassThru,
|
||||
#If specified the result will include equal rows as well. By default only different rows are returned
|
||||
[Switch]$IncludeEqual,
|
||||
#If Specified the result includes only the rows where both are equal
|
||||
[Switch]$ExcludeDifferent
|
||||
)
|
||||
|
||||
#if the filenames don't resolve, give up now.
|
||||
try { $oneFile = ((Resolve-Path -Path $Referencefile -ErrorAction Stop).path -eq (Resolve-Path -Path $Differencefile -ErrorAction Stop).path)}
|
||||
Catch { Write-Warning -Message "Could not Resolve the filenames." ; return }
|
||||
|
||||
#If we have one file , we mush have two different worksheet names. If we have two files we can a single string or two strings.
|
||||
if ($onefile -and ( ($WorkSheetName.count -ne 2) -or $WorkSheetName[0] -eq $WorkSheetName[1] ) ) {
|
||||
Write-Warning -Message "If both the Reference and difference file are the same then worksheet name must provide 2 different names"
|
||||
return
|
||||
}
|
||||
if ($WorkSheetName.count -eq 2) {$worksheet1 = $WorkSheetName[0] ; $WorkSheet2 = $WorkSheetName[1]}
|
||||
elseif ($WorkSheetName -is [string]) {$worksheet1 = $WorkSheet2 = $WorkSheetName}
|
||||
else {Write-Warning -Message "You must provide either a single worksheet name or two names." ; return }
|
||||
|
||||
$params= @{ ErrorAction = [System.Management.Automation.ActionPreference]::Stop }
|
||||
foreach ($p in @("HeaderName","NoHeader","StartRow")) {if ($PSBoundParameters[$p]) {$params[$p] = $PSBoundParameters[$p]}}
|
||||
try {
|
||||
$Sheet1 = Import-Excel -Path $Referencefile -WorksheetName $WorkSheet1 @params
|
||||
$Sheet2 = Import-Excel -Path $Differencefile -WorksheetName $WorkSheet2 @Params
|
||||
}
|
||||
Catch {Write-Warning -Message "Could not read the worksheet from $Referencefile and/or $Differencefile." ; return }
|
||||
|
||||
#Get Column headings and create a hash table of Name to column letter.
|
||||
$headings = $Sheet1[-1].psobject.Properties.name # This preserves the sequence - using get-member would sort them alphabetically!
|
||||
$headings | ForEach-Object -Begin {$columns = @{} ; $i=65 } -Process {$Columns[$_] = [char]($i ++) }
|
||||
|
||||
#Make a list of property headings using the Property (default "*") and ExcludeProperty parameters
|
||||
if ($Key -eq "Name" -and $NoHeader) {$key = "p1"}
|
||||
$propList = @()
|
||||
foreach ($p in $Property) {$propList += ($headings.where({$_ -like $p}) )}
|
||||
foreach ($p in $ExcludeProperty) {$propList = $propList.where({$_ -notlike $p}) }
|
||||
if (($headings -contains $key) -and ($propList -notcontains $Key)) {$propList += $Key}
|
||||
$propList = $propList | Select-Object -Unique
|
||||
if ($propList.Count -eq 0) {Write-Warning -Message "No Columns are selected with -Property = '$Property' and -excludeProperty = '$ExcludeProperty'." ; return}
|
||||
|
||||
#Add RowNumber, Sheetname and file name to every row
|
||||
$FirstDataRow = $startRow + 1
|
||||
if ($Headername -or $NoHeader) {$FirstDataRow -- }
|
||||
$i = $FirstDataRow ; foreach ($row in $Sheet1) {Add-Member -InputObject $row -MemberType NoteProperty -Name "_Row" -Value ($i ++)
|
||||
Add-Member -InputObject $row -MemberType NoteProperty -Name "_Sheet" -Value $worksheet1
|
||||
Add-Member -InputObject $row -MemberType NoteProperty -Name "_File" -Value $Referencefile}
|
||||
$i = $FirstDataRow ; foreach ($row in $Sheet2) {Add-Member -InputObject $row -MemberType NoteProperty -Name "_Row" -Value ($i ++)
|
||||
Add-Member -InputObject $row -MemberType NoteProperty -Name "_Sheet" -Value $worksheet2
|
||||
Add-Member -InputObject $row -MemberType NoteProperty -Name "_File" -Value $Differencefile}
|
||||
|
||||
if ($ExcludeDifferent -and -not $IncludeEqual) {$IncludeEqual = $true}
|
||||
#Do the comparison and add file,sheet and row to the result - these are prefixed with "_" to show they are added the addition will fail if the sheet has these properties so split the operations
|
||||
[PSCustomObject[]]$diff = Compare-Object -ReferenceObject $Sheet1 -DifferenceObject $Sheet2 -Property $propList -PassThru -IncludeEqual:$IncludeEqual -ExcludeDifferent:$ExcludeDifferent |
|
||||
Sort-Object -Property "_Row","File"
|
||||
|
||||
#if BackgroundColor was specified, set it on extra or extra or changed rows
|
||||
if ($diff -and $BackgroundColor) {
|
||||
#Differences may only exist in one file. So gather the changes for each file; open the file, update each impacted row in the shee, save the file
|
||||
$updates = $diff.where({$_.SideIndicator -ne "=="}) | Group-object -Property "_File"
|
||||
foreach ($file in $updates) {
|
||||
try {$xl = Open-ExcelPackage -Path $file.name }
|
||||
catch {Write-warning -Message "Can't open $($file.Name) for writing." ; return}
|
||||
if ($AllDataBackgroundColor) {
|
||||
$file.Group._sheet | Sort-Object -Unique | ForEach-Object {
|
||||
$ws = $xl.Workbook.Worksheets[$_]
|
||||
if ($headerName) {$range = "A" + $startrow + ":" + $ws.dimension.end.address}
|
||||
else {$range = "A" + ($startrow + 1) + ":" + $ws.dimension.end.address}
|
||||
Set-Format -WorkSheet $ws -BackgroundColor $AllDataBackgroundColor -Range $Range
|
||||
}
|
||||
}
|
||||
foreach ($row in $file.group) {
|
||||
$ws = $xl.Workbook.Worksheets[$row._Sheet]
|
||||
$range = $ws.Dimension -replace "\d+",$row._row
|
||||
Set-Format -WorkSheet $ws -Range $range -BackgroundColor $BackgroundColor
|
||||
}
|
||||
if ($TabColor) {
|
||||
foreach ($tab in ($file.group._sheet | Select-Object -Unique)) {
|
||||
$xl.Workbook.Worksheets[$tab].TabColor = $TabColor
|
||||
}
|
||||
}
|
||||
$xl.save() ; $xl.Stream.Close() ; $xl.Dispose()
|
||||
}
|
||||
}
|
||||
#if font colour was specified, set it on changed properties where the same key appears in both sheets.
|
||||
if ($diff -and $FontColor -and ($propList -contains $Key) ) {
|
||||
$updates = $diff.where({$_.SideIndicator -ne "=="}) | Group-object -Property $Key | Where-Object {$_.count -eq 2}
|
||||
if ($updates) {
|
||||
$XL1 = Open-ExcelPackage -path $Referencefile
|
||||
if ($oneFile ) {$xl2 = $xl1}
|
||||
else {$xl2 = Open-ExcelPackage -path $Differencefile }
|
||||
foreach ($u in $updates) {
|
||||
foreach ($p in $propList) {
|
||||
if($u.Group[0].$p -ne $u.Group[1].$p ) {
|
||||
Set-Format -WorkSheet $xl1.Workbook.Worksheets[$u.Group[0]._sheet] -Range ($Columns[$p] + $u.Group[0]._Row) -FontColor $FontColor
|
||||
Set-Format -WorkSheet $xl2.Workbook.Worksheets[$u.Group[1]._sheet] -Range ($Columns[$p] + $u.Group[1]._Row) -FontColor $FontColor
|
||||
}
|
||||
}
|
||||
}
|
||||
$xl1.Save() ; $xl1.Stream.Close() ; $xl1.Dispose()
|
||||
if (-not $oneFile) {$xl2.Save() ; $xl2.Stream.Close() ; $xl2.Dispose()}
|
||||
}
|
||||
}
|
||||
elseif ($diff -and $FontColor) {Write-Warning -Message "To match rows to set changed cells, you must specify -Key and it must match one of the included properties." }
|
||||
|
||||
#if nothing was found write a message which wont be redirected
|
||||
if (-not $diff) {Write-Host "Comparison of $Referencefile::$worksheet1 and $Differencefile::$WorkSheet2 returned no results." }
|
||||
|
||||
if ($show) {
|
||||
Start-Process -FilePath $Referencefile
|
||||
if (-not $oneFile) { Start-Process -FilePath $Differencefile }
|
||||
if ($GridView) { Write-Warning -Message "-GridView is ignored when -Show is specified" }
|
||||
}
|
||||
elseif ($GridView -and $propList -contains $key) {
|
||||
|
||||
|
||||
if ($IncludeEqual -and -not $ExcludeDifferent) {
|
||||
$GroupedRows = $diff | Group-Object -Property $key
|
||||
}
|
||||
else { #to get the right now numbers on the grid we need to have all the rows.
|
||||
$GroupedRows = Compare-Object -ReferenceObject $Sheet1 -DifferenceObject $Sheet2 -Property $propList -PassThru -IncludeEqual |
|
||||
Group-Object -Property $key
|
||||
}
|
||||
#Additions, deletions and unchanged rows will give a group of 1; changes will give a group of 2 .
|
||||
|
||||
#If one sheet has extra rows we can get a single "==" result from compare, but with the row from the reference sheet
|
||||
#but the row in the other sheet might so we will look up the row number from the key field build a hash table for that
|
||||
$Sheet2 | ForEach-Object -Begin {$Rowhash = @{} } -Process {$Rowhash[$_.$key] = $_._row }
|
||||
|
||||
$ExpandedDiff = ForEach ($g in $GroupedRows) {
|
||||
#we're going to create a custom object from a hash table. We want the fields to be ordered
|
||||
$hash = [ordered]@{}
|
||||
foreach ($result IN $g.Group) {
|
||||
# if result indicates equal or "in Reference" set the reference side row. If we did that on a previous result keep it. Otherwise set to "blank"
|
||||
if ($result.sideindicator -ne "=>") {$hash["<Row"] = $result._Row }
|
||||
elseif (-not $hash["<Row"]) {$hash["<Row"] = "" }
|
||||
#if we have already set the side, this is the second record, so set side to indicate "changed"
|
||||
if ($hash.Side) {$hash.side = "<>"} else {$hash["Side"] = $result.sideindicator}
|
||||
#if result is "in reference" and we don't have a matching "in difference" (meaning a change) the lookup will be blank. Which we want.
|
||||
$hash[">Row"] = $Rowhash[$g.Name]
|
||||
#position the key as the next field (only appears once)
|
||||
$Hash[$key] = $g.Name
|
||||
#For all the other fields we care about create <=FieldName and/or =>FieldName
|
||||
foreach ($p in $propList.Where({$_ -ne $key})) {
|
||||
if ($result.SideIndicator -eq "==") {$hash[("=>$P")] = $hash[("<=$P")] =$result.$P}
|
||||
else {$hash[($result.SideIndicator+$P)] =$result.$P}
|
||||
}
|
||||
}
|
||||
[Pscustomobject]$hash
|
||||
}
|
||||
|
||||
#Sort by reference row number, and fill in any blanks in the difference-row column
|
||||
$ExpandedDiff = $ExpandedDiff | Sort-Object -Property "<row"
|
||||
for ($i = 1; $i -lt $ExpandedDiff.Count; $i++) {if (-not $ExpandedDiff[$i].">row") {$ExpandedDiff[$i].">row" = $ExpandedDiff[$i-1].">row" } }
|
||||
#Sort by difference row number, and fill in any blanks in the reference-row column
|
||||
$ExpandedDiff = $ExpandedDiff | Sort-Object -Property ">row"
|
||||
for ($i = 1; $i -lt $ExpandedDiff.Count; $i++) {if (-not $ExpandedDiff[$i]."<row") {$ExpandedDiff[$i]."<row" = $ExpandedDiff[$i-1]."<row" } }
|
||||
|
||||
#if we had to put the equal rows back, take them out; sort, make sure all the columns are present in row 1 so the grid puts them in, and output
|
||||
if ( $ExcludeDifferent) {$ExpandedDiff = $ExpandedDiff.where({$_.side -eq "=="}) | Sort-Object -Property "<row" ,">row" }
|
||||
elseif ( $IncludeEqual) {$ExpandedDiff = $ExpandedDiff | Sort-Object -Property "<row" ,">row" }
|
||||
else {$ExpandedDiff = $ExpandedDiff.where({$_.side -ne "=="}) | Sort-Object -Property "<row" ,">row" }
|
||||
$ExpandedDiff | Update-FirstObjectProperties | Out-GridView -Title "Comparing $Referencefile::$worksheet1 (<=) with $Differencefile::$WorkSheet2 (=>)"
|
||||
}
|
||||
elseif ($GridView ) {Write-Warning -Message "To use -GridView you must specify -Key and it must match one of the included properties." }
|
||||
elseif (-not $PassThru) {return ($diff | Select-Object -Property (@(@{n="_Side";e={$_.SideIndicator}},"_File" ,"_Sheet","_Row") + $propList))}
|
||||
if ( $PassThru) {return $diff }
|
||||
}
|
||||
523
compare-worksheet.ps1
Normal file
523
compare-worksheet.ps1
Normal file
@@ -0,0 +1,523 @@
|
||||
Function Compare-WorkSheet {
|
||||
<#
|
||||
.Synopsis
|
||||
Compares two worksheets with the same name in different files.
|
||||
.Description
|
||||
This command takes two file names, a worksheet name and a name for a key column.
|
||||
It reads the worksheet from each file and decides the column names.
|
||||
It builds as hashtable of the key column values and the rows they appear in
|
||||
It then uses PowerShell's compare object command to compare the sheets (explicity checking all column names which have not been excluded)
|
||||
For the difference rows it adds the row number for the key of that row - we have to add the key after doing the comparison,
|
||||
otherwise rows will be considered as different simply because they have different row numbers
|
||||
We also add the name of the file in which the difference occurs.
|
||||
If -BackgroundColor is specified the difference rows will be changed to that background.
|
||||
.Example
|
||||
Compare-WorkSheet -Referencefile 'Server56.xlsx' -Differencefile 'Server57.xlsx' -WorkSheetName Products -key IdentifyingNumber -ExcludeProperty Install* | format-table
|
||||
The two workbooks in this example contain the result of redirecting a subset of properties from Get-WmiObject -Class win32_product to Export-Excel
|
||||
The command compares the "products" pages in the two workbooks, but we don't want to register a differnce if if the software was installed on a
|
||||
different date or from a different place, so Excluding Install* removes InstallDate and InstallSource.
|
||||
This data doesn't have a "name" column" so we specify the "IdentifyingNumber" column as the key.
|
||||
The results will be presented as a table.
|
||||
.Example
|
||||
compare-WorkSheet "Server54.xlsx" "Server55.xlsx" -WorkSheetName services -GridView
|
||||
This time two workbooks contain the result of redirecting Get-WmiObject -Class win32_service to Export-Excel
|
||||
Here the -Differencefile and -Referencefile parameter switches are assumed , and the default setting for -key ("Name") works for services
|
||||
This will display the differences between the "services" sheets using a grid view
|
||||
.Example
|
||||
Compare-WorkSheet 'Server54.xlsx' 'Server55.xlsx' -WorkSheetName Services -BackgroundColor lightGreen
|
||||
This version of the command outputs the differences between the "services" pages and also highlights any different rows in the spreadsheet files.
|
||||
.Example
|
||||
Compare-WorkSheet 'Server54.xlsx' 'Server55.xlsx' -WorkSheetName Services -BackgroundColor lightGreen -FontColor Red -Show
|
||||
This builds on the previous example: this time Where two changed rows have the value in the "name" column (the default value for -key),
|
||||
this version adds highlighting of the changed cells in red; and then opens the Excel file.
|
||||
.Example
|
||||
Compare-WorkSheet 'Pester-tests.xlsx' 'Pester-tests.xlsx' -WorkSheetName 'Server1','Server2' -Property "full Description","Executed","Result" -Key "full Description"
|
||||
This time the reference file and the difference file are the same file and two different sheets are used. Because the tests include the
|
||||
machine name and time the test was run the command specifies a limited set of columns should be used.
|
||||
.Example
|
||||
Compare-WorkSheet 'Server54.xlsx' 'Server55.xlsx' -WorkSheetName general -Startrow 2 -Headername Label,value -Key Label -GridView -ExcludeDifferent
|
||||
The "General" page has a title and two unlabelled columns with a row forCPU, Memory, Domain, Disk and so on
|
||||
So the command is instructed to starts at row 2 to skip the title and to name the columns: the first is "label" and the Second "Value";
|
||||
the label acts as the key. This time we interested the rows which are the same in both sheets,
|
||||
and the result is displayed using grid view. Note that grid view works best when the number of columns is small.
|
||||
.Example
|
||||
Compare-WorkSheet 'Server1.xlsx' 'Server2.xlsx' -WorkSheetName general -Startrow 2 -Headername Label,value -Key Label -BackgroundColor White -Show -AllDataBackgroundColor LightGray
|
||||
This version of the previous command lightlights all the cells in lightgray and then sets the changed rows back to white; only
|
||||
the unchanged rows are highlighted
|
||||
#>
|
||||
[cmdletbinding(DefaultParameterSetName)]
|
||||
Param(
|
||||
#First file to compare
|
||||
[parameter(Mandatory=$true,Position=0)]
|
||||
$Referencefile ,
|
||||
#Second file to compare
|
||||
[parameter(Mandatory=$true,Position=1)]
|
||||
$Differencefile ,
|
||||
#Name(s) of worksheets to compare.
|
||||
$WorkSheetName = "Sheet1",
|
||||
#Properties to include in the DIFF - supports wildcards, default is "*"
|
||||
$Property = "*" ,
|
||||
#Properties to exclude from the the search - supports wildcards
|
||||
$ExcludeProperty ,
|
||||
#Specifies custom property names to use, instead of the values defined in the column headers of the TopRow.
|
||||
[Parameter(ParameterSetName='B', Mandatory)]
|
||||
[String[]]$Headername,
|
||||
#Automatically generate property names (P1, P2, P3, ..) instead of the using the values the top row of the sheet
|
||||
[Parameter(ParameterSetName='C', Mandatory)]
|
||||
[switch]$NoHeader,
|
||||
#The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row.
|
||||
[int]$Startrow = 1,
|
||||
#If specified, highlights all the cells - so you can make Equal cells one colour, and Diff cells another.
|
||||
[System.Drawing.Color]$AllDataBackgroundColor,
|
||||
#If specified, highlights the DIFF rows
|
||||
[System.Drawing.Color]$BackgroundColor,
|
||||
#If specified identifies the tabs which contain DIFF rows (ignored if -backgroundColor is omitted)
|
||||
[System.Drawing.Color]$TabColor,
|
||||
#Name of a column which is unique and will be used to add a row to the DIFF object, default is "Name"
|
||||
$Key = "Name" ,
|
||||
#If specified, highlights the DIFF columns in rows which have the same key.
|
||||
[System.Drawing.Color]$FontColor,
|
||||
#If specified opens the Excel workbooks instead of outputting the diff to the console (unless -passthru is also specified)
|
||||
[Switch]$Show,
|
||||
#If specified, the command tries to the show the DIFF in a Gridview and not on the console. (unless-Passthru is also specified). This Works best with few columns selected, and requires a key
|
||||
[switch]$GridView,
|
||||
#If specified -Passthrough full set of diff data is returned without filtering to the specified properties
|
||||
[Switch]$PassThru,
|
||||
#If specified the result will include equal rows as well. By default only different rows are returned
|
||||
[Switch]$IncludeEqual,
|
||||
#If Specified the result includes only the rows where both are equal
|
||||
[Switch]$ExcludeDifferent
|
||||
)
|
||||
|
||||
#if the filenames don't resolve, give up now.
|
||||
try { $oneFile = ((Resolve-Path -Path $Referencefile -ErrorAction Stop).path -eq (Resolve-Path -Path $Differencefile -ErrorAction Stop).path)}
|
||||
Catch { Write-Warning -Message "Could not Resolve the filenames." ; return }
|
||||
|
||||
#If we have one file , we mush have two different worksheet names. If we have two files we can a single string or two strings.
|
||||
if ($onefile -and ( ($WorkSheetName.count -ne 2) -or $WorkSheetName[0] -eq $WorkSheetName[1] ) ) {
|
||||
Write-Warning -Message "If both the Reference and difference file are the same then worksheet name must provide 2 different names"
|
||||
return
|
||||
}
|
||||
if ($WorkSheetName.count -eq 2) {$worksheet1 = $WorkSheetName[0] ; $WorkSheet2 = $WorkSheetName[1]}
|
||||
elseif ($WorkSheetName -is [string]) {$worksheet1 = $WorkSheet2 = $WorkSheetName}
|
||||
else {Write-Warning -Message "You must provide either a single worksheet name or two names." ; return }
|
||||
|
||||
$params= @{ ErrorAction = [System.Management.Automation.ActionPreference]::Stop }
|
||||
foreach ($p in @("HeaderName","NoHeader","StartRow")) {if ($PSBoundParameters[$p]) {$params[$p] = $PSBoundParameters[$p]}}
|
||||
try {
|
||||
$Sheet1 = Import-Excel -Path $Referencefile -WorksheetName $WorkSheet1 @params
|
||||
$Sheet2 = Import-Excel -Path $Differencefile -WorksheetName $WorkSheet2 @Params
|
||||
}
|
||||
Catch {Write-Warning -Message "Could not read the worksheet from $Referencefile and/or $Differencefile." ; return }
|
||||
|
||||
#Get Column headings and create a hash table of Name to column letter.
|
||||
$headings = $Sheet1[-1].psobject.Properties.name # This preserves the sequence - using get-member would sort them alphabetically!
|
||||
$headings | ForEach-Object -Begin {$columns = @{} ; $i=65 } -Process {$Columns[$_] = [char]($i ++) }
|
||||
|
||||
#Make a list of property headings using the Property (default "*") and ExcludeProperty parameters
|
||||
if ($Key -eq "Name" -and $NoHeader) {$key = "p1"}
|
||||
$propList = @()
|
||||
foreach ($p in $Property) {$propList += ($headings.where({$_ -like $p}) )}
|
||||
foreach ($p in $ExcludeProperty) {$propList = $propList.where({$_ -notlike $p}) }
|
||||
if (($headings -contains $key) -and ($propList -notcontains $Key)) {$propList += $Key}
|
||||
$propList = $propList | Select-Object -Unique
|
||||
if ($propList.Count -eq 0) {Write-Warning -Message "No Columns are selected with -Property = '$Property' and -excludeProperty = '$ExcludeProperty'." ; return}
|
||||
|
||||
#Add RowNumber, Sheetname and file name to every row
|
||||
$FirstDataRow = $startRow + 1
|
||||
if ($Headername -or $NoHeader) {$FirstDataRow -- }
|
||||
$i = $FirstDataRow ; foreach ($row in $Sheet1) {Add-Member -InputObject $row -MemberType NoteProperty -Name "_Row" -Value ($i ++)
|
||||
Add-Member -InputObject $row -MemberType NoteProperty -Name "_Sheet" -Value $worksheet1
|
||||
Add-Member -InputObject $row -MemberType NoteProperty -Name "_File" -Value $Referencefile}
|
||||
$i = $FirstDataRow ; foreach ($row in $Sheet2) {Add-Member -InputObject $row -MemberType NoteProperty -Name "_Row" -Value ($i ++)
|
||||
Add-Member -InputObject $row -MemberType NoteProperty -Name "_Sheet" -Value $worksheet2
|
||||
Add-Member -InputObject $row -MemberType NoteProperty -Name "_File" -Value $Differencefile}
|
||||
|
||||
if ($ExcludeDifferent -and -not $IncludeEqual) {$IncludeEqual = $true}
|
||||
#Do the comparison and add file,sheet and row to the result - these are prefixed with "_" to show they are added the addition will fail if the sheet has these properties so split the operations
|
||||
[PSCustomObject[]]$diff = Compare-Object -ReferenceObject $Sheet1 -DifferenceObject $Sheet2 -Property $propList -PassThru -IncludeEqual:$IncludeEqual -ExcludeDifferent:$ExcludeDifferent |
|
||||
Sort-Object -Property "_Row","File"
|
||||
|
||||
#if BackgroundColor was specified, set it on extra or extra or changed rows
|
||||
if ($diff -and $BackgroundColor) {
|
||||
#Differences may only exist in one file. So gather the changes for each file; open the file, update each impacted row in the shee, save the file
|
||||
$updates = $diff.where({$_.SideIndicator -ne "=="}) | Group-object -Property "_File"
|
||||
foreach ($file in $updates) {
|
||||
try {$xl = Open-ExcelPackage -Path $file.name }
|
||||
catch {Write-warning -Message "Can't open $($file.Name) for writing." ; return}
|
||||
if ($AllDataBackgroundColor) {
|
||||
$file.Group._sheet | Sort-Object -Unique | ForEach-Object {
|
||||
$ws = $xl.Workbook.Worksheets[$_]
|
||||
if ($headerName) {$range = "A" + $startrow + ":" + $ws.dimension.end.address}
|
||||
else {$range = "A" + ($startrow + 1) + ":" + $ws.dimension.end.address}
|
||||
Set-Format -WorkSheet $ws -BackgroundColor $AllDataBackgroundColor -Range $Range
|
||||
}
|
||||
}
|
||||
foreach ($row in $file.group) {
|
||||
$ws = $xl.Workbook.Worksheets[$row._Sheet]
|
||||
$range = $ws.Dimension -replace "\d+",$row._row
|
||||
Set-Format -WorkSheet $ws -Range $range -BackgroundColor $BackgroundColor
|
||||
}
|
||||
if ($TabColor) {
|
||||
foreach ($tab in ($file.group._sheet | Select-Object -Unique)) {
|
||||
$xl.Workbook.Worksheets[$tab].TabColor = $TabColor
|
||||
}
|
||||
}
|
||||
$xl.save() ; $xl.Stream.Close() ; $xl.Dispose()
|
||||
}
|
||||
}
|
||||
#if font colour was specified, set it on changed properties where the same key appears in both sheets.
|
||||
if ($diff -and $FontColor -and ($propList -contains $Key) ) {
|
||||
$updates = $diff.where({$_.SideIndicator -ne "=="}) | Group-object -Property $Key | Where-Object {$_.count -eq 2}
|
||||
if ($updates) {
|
||||
$XL1 = Open-ExcelPackage -path $Referencefile
|
||||
if ($oneFile ) {$xl2 = $xl1}
|
||||
else {$xl2 = Open-ExcelPackage -path $Differencefile }
|
||||
foreach ($u in $updates) {
|
||||
foreach ($p in $propList) {
|
||||
if ($u.group[0]._file -eq $Referencefile) {
|
||||
$ws1 = $xl1.Workbook.Worksheets[$u.Group[0]._sheet]
|
||||
$ws2 = $xl2.Workbook.Worksheets[$u.Group[1]._sheet]
|
||||
}
|
||||
else {
|
||||
$ws1 = $xl2.Workbook.Worksheets[$u.Group[0]._sheet]
|
||||
$ws2 = $xl1.Workbook.Worksheets[$u.Group[1]._sheet]
|
||||
}
|
||||
if($u.Group[0].$p -ne $u.Group[1].$p ) {
|
||||
Set-Format -WorkSheet $ws1 -Range ($Columns[$p] + $u.Group[0]._Row) -FontColor $FontColor
|
||||
Set-Format -WorkSheet $ws1 -Range ($Columns[$p] + $u.Group[1]._Row) -FontColor $FontColor
|
||||
}
|
||||
}
|
||||
}
|
||||
$xl1.Save() ; $xl1.Stream.Close() ; $xl1.Dispose()
|
||||
if (-not $oneFile) {$xl2.Save() ; $xl2.Stream.Close() ; $xl2.Dispose()}
|
||||
}
|
||||
}
|
||||
elseif ($diff -and $FontColor) {Write-Warning -Message "To match rows to set changed cells, you must specify -Key and it must match one of the included properties." }
|
||||
|
||||
#if nothing was found write a message which wont be redirected
|
||||
if (-not $diff) {Write-Host "Comparison of $Referencefile::$worksheet1 and $Differencefile::$WorkSheet2 returned no results." }
|
||||
|
||||
if ($show) {
|
||||
Start-Process -FilePath $Referencefile
|
||||
if (-not $oneFile) { Start-Process -FilePath $Differencefile }
|
||||
if ($GridView) { Write-Warning -Message "-GridView is ignored when -Show is specified" }
|
||||
}
|
||||
elseif ($GridView -and $propList -contains $key) {
|
||||
|
||||
|
||||
if ($IncludeEqual -and -not $ExcludeDifferent) {
|
||||
$GroupedRows = $diff | Group-Object -Property $key
|
||||
}
|
||||
else { #to get the right now numbers on the grid we need to have all the rows.
|
||||
$GroupedRows = Compare-Object -ReferenceObject $Sheet1 -DifferenceObject $Sheet2 -Property $propList -PassThru -IncludeEqual |
|
||||
Group-Object -Property $key
|
||||
}
|
||||
#Additions, deletions and unchanged rows will give a group of 1; changes will give a group of 2 .
|
||||
|
||||
#If one sheet has extra rows we can get a single "==" result from compare, but with the row from the reference sheet
|
||||
#but the row in the other sheet might so we will look up the row number from the key field build a hash table for that
|
||||
$Sheet2 | ForEach-Object -Begin {$Rowhash = @{} } -Process {$Rowhash[$_.$key] = $_._row }
|
||||
|
||||
$ExpandedDiff = ForEach ($g in $GroupedRows) {
|
||||
#we're going to create a custom object from a hash table. We want the fields to be ordered
|
||||
$hash = [ordered]@{}
|
||||
foreach ($result IN $g.Group) {
|
||||
# if result indicates equal or "in Reference" set the reference side row. If we did that on a previous result keep it. Otherwise set to "blank"
|
||||
if ($result.sideindicator -ne "=>") {$hash["<Row"] = $result._Row }
|
||||
elseif (-not $hash["<Row"]) {$hash["<Row"] = "" }
|
||||
#if we have already set the side, this is the second record, so set side to indicate "changed"
|
||||
if ($hash.Side) {$hash.side = "<>"} else {$hash["Side"] = $result.sideindicator}
|
||||
#if result is "in reference" and we don't have a matching "in difference" (meaning a change) the lookup will be blank. Which we want.
|
||||
$hash[">Row"] = $Rowhash[$g.Name]
|
||||
#position the key as the next field (only appears once)
|
||||
$Hash[$key] = $g.Name
|
||||
#For all the other fields we care about create <=FieldName and/or =>FieldName
|
||||
foreach ($p in $propList.Where({$_ -ne $key})) {
|
||||
if ($result.SideIndicator -eq "==") {$hash[("=>$P")] = $hash[("<=$P")] =$result.$P}
|
||||
else {$hash[($result.SideIndicator+$P)] =$result.$P}
|
||||
}
|
||||
}
|
||||
[Pscustomobject]$hash
|
||||
}
|
||||
|
||||
#Sort by reference row number, and fill in any blanks in the difference-row column
|
||||
$ExpandedDiff = $ExpandedDiff | Sort-Object -Property "<row"
|
||||
for ($i = 1; $i -lt $ExpandedDiff.Count; $i++) {if (-not $ExpandedDiff[$i].">row") {$ExpandedDiff[$i].">row" = $ExpandedDiff[$i-1].">row" } }
|
||||
#Sort by difference row number, and fill in any blanks in the reference-row column
|
||||
$ExpandedDiff = $ExpandedDiff | Sort-Object -Property ">row"
|
||||
for ($i = 1; $i -lt $ExpandedDiff.Count; $i++) {if (-not $ExpandedDiff[$i]."<row") {$ExpandedDiff[$i]."<row" = $ExpandedDiff[$i-1]."<row" } }
|
||||
|
||||
#if we had to put the equal rows back, take them out; sort, make sure all the columns are present in row 1 so the grid puts them in, and output
|
||||
if ( $ExcludeDifferent) {$ExpandedDiff = $ExpandedDiff.where({$_.side -eq "=="}) | Sort-Object -Property "<row" ,">row" }
|
||||
elseif ( $IncludeEqual) {$ExpandedDiff = $ExpandedDiff | Sort-Object -Property "<row" ,">row" }
|
||||
else {$ExpandedDiff = $ExpandedDiff.where({$_.side -ne "=="}) | Sort-Object -Property "<row" ,">row" }
|
||||
$ExpandedDiff | Update-FirstObjectProperties | Out-GridView -Title "Comparing $Referencefile::$worksheet1 (<=) with $Differencefile::$WorkSheet2 (=>)"
|
||||
}
|
||||
elseif ($GridView ) {Write-Warning -Message "To use -GridView you must specify -Key and it must match one of the included properties." }
|
||||
elseif (-not $PassThru) {return ($diff | Select-Object -Property (@(@{n="_Side";e={$_.SideIndicator}},"_File" ,"_Sheet","_Row") + $propList))}
|
||||
if ( $PassThru) {return $diff }
|
||||
}
|
||||
=======
|
||||
Function Compare-WorkSheet {
|
||||
<#
|
||||
.Synopsis
|
||||
Compares two worksheets with the same name in different files.
|
||||
.Description
|
||||
This command takes two file names, a worksheet name and a name for a key column.
|
||||
It reads the worksheet from each file and decides the column names.
|
||||
It builds as hashtable of the key column values and the rows they appear in
|
||||
It then uses PowerShell's compare object command to compare the sheets (explicity checking all column names which have not been excluded)
|
||||
For the difference rows it adds the row number for the key of that row - we have to add the key after doing the comparison,
|
||||
otherwise rows will be considered as different simply because they have different row numbers
|
||||
We also add the name of the file in which the difference occurs.
|
||||
If -BackgroundColor is specified the difference rows will be changed to that background.
|
||||
.Example
|
||||
Compare-WorkSheet -Referencefile 'Server56.xlsx' -Differencefile 'Server57.xlsx' -WorkSheetName Products -key IdentifyingNumber -ExcludeProperty Install* | format-table
|
||||
The two workbooks in this example contain the result of redirecting a subset of properties from Get-WmiObject -Class win32_product to Export-Excel
|
||||
The command compares the "products" pages in the two workbooks, but we don't want to register a differnce if if the software was installed on a
|
||||
different date or from a different place, so Excluding Install* removes InstallDate and InstallSource.
|
||||
This data doesn't have a "name" column" so we specify the "IdentifyingNumber" column as the key.
|
||||
The results will be presented as a table.
|
||||
.Example
|
||||
compare-WorkSheet "Server54.xlsx" "Server55.xlsx" -WorkSheetName services -GridView
|
||||
This time two workbooks contain the result of redirecting Get-WmiObject -Class win32_service to Export-Excel
|
||||
Here the -Differencefile and -Referencefile parameter switches are assumed , and the default setting for -key ("Name") works for services
|
||||
This will display the differences between the "services" sheets using a grid view
|
||||
.Example
|
||||
Compare-WorkSheet 'Server54.xlsx' 'Server55.xlsx' -WorkSheetName Services -BackgroundColor lightGreen
|
||||
This version of the command outputs the differences between the "services" pages and also highlights any different rows in the spreadsheet files.
|
||||
.Example
|
||||
Compare-WorkSheet 'Server54.xlsx' 'Server55.xlsx' -WorkSheetName Services -BackgroundColor lightGreen -FontColor Red -Show
|
||||
This builds on the previous example: this time Where two changed rows have the value in the "name" column (the default value for -key),
|
||||
this version adds highlighting of the changed cells in red; and then opens the Excel file.
|
||||
.Example
|
||||
Compare-WorkSheet 'Pester-tests.xlsx' 'Pester-tests.xlsx' -WorkSheetName 'Server1','Server2' -Property "full Description","Executed","Result" -Key "full Description"
|
||||
This time the reference file and the difference file are the same file and two different sheets are used. Because the tests include the
|
||||
machine name and time the test was run the command specifies a limited set of columns should be used.
|
||||
.Example
|
||||
Compare-WorkSheet 'Server54.xlsx' 'Server55.xlsx' -WorkSheetName general -Startrow 2 -Headername Label,value -Key Label -GridView -ExcludeDifferent
|
||||
The "General" page has a title and two unlabelled columns with a row forCPU, Memory, Domain, Disk and so on
|
||||
So the command is instructed to starts at row 2 to skip the title and to name the columns: the first is "label" and the Second "Value";
|
||||
the label acts as the key. This time we interested the rows which are the same in both sheets,
|
||||
and the result is displayed using grid view. Note that grid view works best when the number of columns is small.
|
||||
.Example
|
||||
Compare-WorkSheet 'Server1.xlsx' 'Server2.xlsx' -WorkSheetName general -Startrow 2 -Headername Label,value -Key Label -BackgroundColor White -Show -AllDataBackgroundColor LightGray
|
||||
This version of the previous command lightlights all the cells in lightgray and then sets the changed rows back to white; only
|
||||
the unchanged rows are highlighted
|
||||
#>
|
||||
[cmdletbinding(DefaultParameterSetName)]
|
||||
Param(
|
||||
#First file to compare
|
||||
[parameter(Mandatory=$true,Position=0)]
|
||||
$Referencefile ,
|
||||
#Second file to compare
|
||||
[parameter(Mandatory=$true,Position=1)]
|
||||
$Differencefile ,
|
||||
#Name(s) of worksheets to compare.
|
||||
$WorkSheetName = "Sheet1",
|
||||
#Properties to include in the DIFF - supports wildcards, default is "*"
|
||||
$Property = "*" ,
|
||||
#Properties to exclude from the the search - supports wildcards
|
||||
$ExcludeProperty ,
|
||||
#Specifies custom property names to use, instead of the values defined in the column headers of the TopRow.
|
||||
[Parameter(ParameterSetName='B', Mandatory)]
|
||||
[String[]]$Headername,
|
||||
#Automatically generate property names (P1, P2, P3, ..) instead of the using the values the top row of the sheet
|
||||
[Parameter(ParameterSetName='C', Mandatory)]
|
||||
[switch]$NoHeader,
|
||||
#The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row.
|
||||
[int]$Startrow = 1,
|
||||
#If specified, highlights all the cells - so you can make Equal cells one colour, and Diff cells another.
|
||||
[System.Drawing.Color]$AllDataBackgroundColor,
|
||||
#If specified, highlights the DIFF rows
|
||||
[System.Drawing.Color]$BackgroundColor,
|
||||
#If specified identifies the tabs which contain DIFF rows (ignored if -backgroundColor is omitted)
|
||||
[System.Drawing.Color]$TabColor,
|
||||
#Name of a column which is unique and will be used to add a row to the DIFF object, default is "Name"
|
||||
$Key = "Name" ,
|
||||
#If specified, highlights the DIFF columns in rows which have the same key.
|
||||
[System.Drawing.Color]$FontColor,
|
||||
#If specified opens the Excel workbooks instead of outputting the diff to the console (unless -passthru is also specified)
|
||||
[Switch]$Show,
|
||||
#If specified, the command tries to the show the DIFF in a Gridview and not on the console. (unless-Passthru is also specified). This Works best with few columns selected, and requires a key
|
||||
[switch]$GridView,
|
||||
#If specified -Passthrough full set of diff data is returned without filtering to the specified properties
|
||||
[Switch]$PassThru,
|
||||
#If specified the result will include equal rows as well. By default only different rows are returned
|
||||
[Switch]$IncludeEqual,
|
||||
#If Specified the result includes only the rows where both are equal
|
||||
[Switch]$ExcludeDifferent
|
||||
)
|
||||
|
||||
#if the filenames don't resolve, give up now.
|
||||
try { $oneFile = ((Resolve-Path -Path $Referencefile -ErrorAction Stop).path -eq (Resolve-Path -Path $Differencefile -ErrorAction Stop).path)}
|
||||
Catch { Write-Warning -Message "Could not Resolve the filenames." ; return }
|
||||
|
||||
#If we have one file , we mush have two different worksheet names. If we have two files we can a single string or two strings.
|
||||
if ($onefile -and ( ($WorkSheetName.count -ne 2) -or $WorkSheetName[0] -eq $WorkSheetName[1] ) ) {
|
||||
Write-Warning -Message "If both the Reference and difference file are the same then worksheet name must provide 2 different names"
|
||||
return
|
||||
}
|
||||
if ($WorkSheetName.count -eq 2) {$worksheet1 = $WorkSheetName[0] ; $WorkSheet2 = $WorkSheetName[1]}
|
||||
elseif ($WorkSheetName -is [string]) {$worksheet1 = $WorkSheet2 = $WorkSheetName}
|
||||
else {Write-Warning -Message "You must provide either a single worksheet name or two names." ; return }
|
||||
|
||||
$params= @{ ErrorAction = [System.Management.Automation.ActionPreference]::Stop }
|
||||
foreach ($p in @("HeaderName","NoHeader","StartRow")) {if ($PSBoundParameters[$p]) {$params[$p] = $PSBoundParameters[$p]}}
|
||||
try {
|
||||
$Sheet1 = Import-Excel -Path $Referencefile -WorksheetName $WorkSheet1 @params
|
||||
$Sheet2 = Import-Excel -Path $Differencefile -WorksheetName $WorkSheet2 @Params
|
||||
}
|
||||
Catch {Write-Warning -Message "Could not read the worksheet from $Referencefile and/or $Differencefile." ; return }
|
||||
|
||||
#Get Column headings and create a hash table of Name to column letter.
|
||||
$headings = $Sheet1[-1].psobject.Properties.name # This preserves the sequence - using get-member would sort them alphabetically!
|
||||
$headings | ForEach-Object -Begin {$columns = @{} ; $i=65 } -Process {$Columns[$_] = [char]($i ++) }
|
||||
|
||||
#Make a list of property headings using the Property (default "*") and ExcludeProperty parameters
|
||||
if ($Key -eq "Name" -and $NoHeader) {$key = "p1"}
|
||||
$propList = @()
|
||||
foreach ($p in $Property) {$propList += ($headings.where({$_ -like $p}) )}
|
||||
foreach ($p in $ExcludeProperty) {$propList = $propList.where({$_ -notlike $p}) }
|
||||
if (($headings -contains $key) -and ($propList -notcontains $Key)) {$propList += $Key}
|
||||
$propList = $propList | Select-Object -Unique
|
||||
if ($propList.Count -eq 0) {Write-Warning -Message "No Columns are selected with -Property = '$Property' and -excludeProperty = '$ExcludeProperty'." ; return}
|
||||
|
||||
#Add RowNumber, Sheetname and file name to every row
|
||||
$FirstDataRow = $startRow + 1
|
||||
if ($Headername -or $NoHeader) {$FirstDataRow -- }
|
||||
$i = $FirstDataRow ; foreach ($row in $Sheet1) {Add-Member -InputObject $row -MemberType NoteProperty -Name "_Row" -Value ($i ++)
|
||||
Add-Member -InputObject $row -MemberType NoteProperty -Name "_Sheet" -Value $worksheet1
|
||||
Add-Member -InputObject $row -MemberType NoteProperty -Name "_File" -Value $Referencefile}
|
||||
$i = $FirstDataRow ; foreach ($row in $Sheet2) {Add-Member -InputObject $row -MemberType NoteProperty -Name "_Row" -Value ($i ++)
|
||||
Add-Member -InputObject $row -MemberType NoteProperty -Name "_Sheet" -Value $worksheet2
|
||||
Add-Member -InputObject $row -MemberType NoteProperty -Name "_File" -Value $Differencefile}
|
||||
|
||||
if ($ExcludeDifferent -and -not $IncludeEqual) {$IncludeEqual = $true}
|
||||
#Do the comparison and add file,sheet and row to the result - these are prefixed with "_" to show they are added the addition will fail if the sheet has these properties so split the operations
|
||||
[PSCustomObject[]]$diff = Compare-Object -ReferenceObject $Sheet1 -DifferenceObject $Sheet2 -Property $propList -PassThru -IncludeEqual:$IncludeEqual -ExcludeDifferent:$ExcludeDifferent |
|
||||
Sort-Object -Property "_Row","File"
|
||||
|
||||
#if BackgroundColor was specified, set it on extra or extra or changed rows
|
||||
if ($diff -and $BackgroundColor) {
|
||||
#Differences may only exist in one file. So gather the changes for each file; open the file, update each impacted row in the shee, save the file
|
||||
$updates = $diff.where({$_.SideIndicator -ne "=="}) | Group-object -Property "_File"
|
||||
foreach ($file in $updates) {
|
||||
try {$xl = Open-ExcelPackage -Path $file.name }
|
||||
catch {Write-warning -Message "Can't open $($file.Name) for writing." ; return}
|
||||
if ($AllDataBackgroundColor) {
|
||||
$file.Group._sheet | Sort-Object -Unique | ForEach-Object {
|
||||
$ws = $xl.Workbook.Worksheets[$_]
|
||||
if ($headerName) {$range = "A" + $startrow + ":" + $ws.dimension.end.address}
|
||||
else {$range = "A" + ($startrow + 1) + ":" + $ws.dimension.end.address}
|
||||
Set-Format -WorkSheet $ws -BackgroundColor $AllDataBackgroundColor -Range $Range
|
||||
}
|
||||
}
|
||||
foreach ($row in $file.group) {
|
||||
$ws = $xl.Workbook.Worksheets[$row._Sheet]
|
||||
$range = $ws.Dimension -replace "\d+",$row._row
|
||||
Set-Format -WorkSheet $ws -Range $range -BackgroundColor $BackgroundColor
|
||||
}
|
||||
if ($TabColor) {
|
||||
foreach ($tab in ($file.group._sheet | Select-Object -Unique)) {
|
||||
$xl.Workbook.Worksheets[$tab].TabColor = $TabColor
|
||||
}
|
||||
}
|
||||
$xl.save() ; $xl.Stream.Close() ; $xl.Dispose()
|
||||
}
|
||||
}
|
||||
#if font colour was specified, set it on changed properties where the same key appears in both sheets.
|
||||
if ($diff -and $FontColor -and ($propList -contains $Key) ) {
|
||||
$updates = $diff.where({$_.SideIndicator -ne "=="}) | Group-object -Property $Key | Where-Object {$_.count -eq 2}
|
||||
if ($updates) {
|
||||
$XL1 = Open-ExcelPackage -path $Referencefile
|
||||
if ($oneFile ) {$xl2 = $xl1}
|
||||
else {$xl2 = Open-ExcelPackage -path $Differencefile }
|
||||
foreach ($u in $updates) {
|
||||
foreach ($p in $propList) {
|
||||
if ($u.group[0]._file -eq $Referencefile) {
|
||||
$ws1 = $xl1.Workbook.Worksheets[$u.Group[0]._sheet]
|
||||
$ws2 = $xl2.Workbook.Worksheets[$u.Group[1]._sheet]
|
||||
}
|
||||
else {
|
||||
$ws1 = $xl2.Workbook.Worksheets[$u.Group[0]._sheet]
|
||||
$ws2 = $xl1.Workbook.Worksheets[$u.Group[1]._sheet]
|
||||
}
|
||||
if($u.Group[0].$p -ne $u.Group[1].$p ) {
|
||||
Set-Format -WorkSheet $ws1 -Range ($Columns[$p] + $u.Group[0]._Row) -FontColor $FontColor
|
||||
Set-Format -WorkSheet $ws1 -Range ($Columns[$p] + $u.Group[1]._Row) -FontColor $FontColor
|
||||
}
|
||||
}
|
||||
}
|
||||
$xl1.Save() ; $xl1.Stream.Close() ; $xl1.Dispose()
|
||||
if (-not $oneFile) {$xl2.Save() ; $xl2.Stream.Close() ; $xl2.Dispose()}
|
||||
}
|
||||
}
|
||||
elseif ($diff -and $FontColor) {Write-Warning -Message "To match rows to set changed cells, you must specify -Key and it must match one of the included properties." }
|
||||
|
||||
#if nothing was found write a message which wont be redirected
|
||||
if (-not $diff) {Write-Host "Comparison of $Referencefile::$worksheet1 and $Differencefile::$WorkSheet2 returned no results." }
|
||||
|
||||
if ($show) {
|
||||
Start-Process -FilePath $Referencefile
|
||||
if (-not $oneFile) { Start-Process -FilePath $Differencefile }
|
||||
if ($GridView) { Write-Warning -Message "-GridView is ignored when -Show is specified" }
|
||||
}
|
||||
elseif ($GridView -and $propList -contains $key) {
|
||||
|
||||
|
||||
if ($IncludeEqual -and -not $ExcludeDifferent) {
|
||||
$GroupedRows = $diff | Group-Object -Property $key
|
||||
}
|
||||
else { #to get the right now numbers on the grid we need to have all the rows.
|
||||
$GroupedRows = Compare-Object -ReferenceObject $Sheet1 -DifferenceObject $Sheet2 -Property $propList -PassThru -IncludeEqual |
|
||||
Group-Object -Property $key
|
||||
}
|
||||
#Additions, deletions and unchanged rows will give a group of 1; changes will give a group of 2 .
|
||||
|
||||
#If one sheet has extra rows we can get a single "==" result from compare, but with the row from the reference sheet
|
||||
#but the row in the other sheet might so we will look up the row number from the key field build a hash table for that
|
||||
$Sheet2 | ForEach-Object -Begin {$Rowhash = @{} } -Process {$Rowhash[$_.$key] = $_._row }
|
||||
|
||||
$ExpandedDiff = ForEach ($g in $GroupedRows) {
|
||||
#we're going to create a custom object from a hash table. We want the fields to be ordered
|
||||
$hash = [ordered]@{}
|
||||
foreach ($result IN $g.Group) {
|
||||
# if result indicates equal or "in Reference" set the reference side row. If we did that on a previous result keep it. Otherwise set to "blank"
|
||||
if ($result.sideindicator -ne "=>") {$hash["<Row"] = $result._Row }
|
||||
elseif (-not $hash["<Row"]) {$hash["<Row"] = "" }
|
||||
#if we have already set the side, this is the second record, so set side to indicate "changed"
|
||||
if ($hash.Side) {$hash.side = "<>"} else {$hash["Side"] = $result.sideindicator}
|
||||
#if result is "in reference" and we don't have a matching "in difference" (meaning a change) the lookup will be blank. Which we want.
|
||||
$hash[">Row"] = $Rowhash[$g.Name]
|
||||
#position the key as the next field (only appears once)
|
||||
$Hash[$key] = $g.Name
|
||||
#For all the other fields we care about create <=FieldName and/or =>FieldName
|
||||
foreach ($p in $propList.Where({$_ -ne $key})) {
|
||||
if ($result.SideIndicator -eq "==") {$hash[("=>$P")] = $hash[("<=$P")] =$result.$P}
|
||||
else {$hash[($result.SideIndicator+$P)] =$result.$P}
|
||||
}
|
||||
}
|
||||
[Pscustomobject]$hash
|
||||
}
|
||||
|
||||
#Sort by reference row number, and fill in any blanks in the difference-row column
|
||||
$ExpandedDiff = $ExpandedDiff | Sort-Object -Property "<row"
|
||||
for ($i = 1; $i -lt $ExpandedDiff.Count; $i++) {if (-not $ExpandedDiff[$i].">row") {$ExpandedDiff[$i].">row" = $ExpandedDiff[$i-1].">row" } }
|
||||
#Sort by difference row number, and fill in any blanks in the reference-row column
|
||||
$ExpandedDiff = $ExpandedDiff | Sort-Object -Property ">row"
|
||||
for ($i = 1; $i -lt $ExpandedDiff.Count; $i++) {if (-not $ExpandedDiff[$i]."<row") {$ExpandedDiff[$i]."<row" = $ExpandedDiff[$i-1]."<row" } }
|
||||
|
||||
#if we had to put the equal rows back, take them out; sort, make sure all the columns are present in row 1 so the grid puts them in, and output
|
||||
if ( $ExcludeDifferent) {$ExpandedDiff = $ExpandedDiff.where({$_.side -eq "=="}) | Sort-Object -Property "<row" ,">row" }
|
||||
elseif ( $IncludeEqual) {$ExpandedDiff = $ExpandedDiff | Sort-Object -Property "<row" ,">row" }
|
||||
else {$ExpandedDiff = $ExpandedDiff.where({$_.side -ne "=="}) | Sort-Object -Property "<row" ,">row" }
|
||||
$ExpandedDiff | Update-FirstObjectProperties | Out-GridView -Title "Comparing $Referencefile::$worksheet1 (<=) with $Differencefile::$WorkSheet2 (=>)"
|
||||
}
|
||||
elseif ($GridView ) {Write-Warning -Message "To use -GridView you must specify -Key and it must match one of the included properties." }
|
||||
elseif (-not $PassThru) {return ($diff | Select-Object -Property (@(@{n="_Side";e={$_.SideIndicator}},"_File" ,"_Sheet","_Row") + $propList))}
|
||||
if ( $PassThru) {return $diff }
|
||||
}
|
||||
|
||||
>>>>>>> 9f7884f991c80448091ef56853027f64d98b6cc7
|
||||
Reference in New Issue
Block a user