Merge pull request #378 from jhoneill/master

Bug fixes for add-chart and compare-ws
This commit is contained in:
Doug Finke
2018-07-05 14:21:25 -04:00
committed by GitHub
13 changed files with 1954 additions and 621 deletions

3
.gitignore vendored
View File

@@ -42,6 +42,7 @@ Network Trash Folder
Temporary Items
.apdisk
testExport.xlsx
test.xlsx
test.ps1
testPwd.xlsx
test.csv
@@ -55,3 +56,5 @@ test.xlsx
testCCFMT.ps1
testHide.ps1
ImportExcel.zip
.vscode/launch.json

Binary file not shown.

View File

@@ -356,7 +356,7 @@
[Int]$TitleSize = 22,
[System.Drawing.Color]$TitleBackgroundColor,
[Switch]$IncludePivotTable,
[String]$PivotTableName,
[String]$PivotTableName,
[String[]]$PivotRows,
[String[]]$PivotColumns,
$PivotData,
@@ -458,17 +458,10 @@
#Write-Verbose "Cell '$Row`:$ColumnIndex' header '$Name' add value '$_' as value"
break
}
{(($NoNumberConversion) -and ($NoNumberConversion -contains $Name)) -or
($NoNumberConversion -eq '*')} {
#Save text without it to converting to number
$TargetCell.Value = $_
#Write-Verbose "Cell '$Row`:$ColumnIndex' header '$Name' add value '$($TargetCell.Value)' unconverted"
break
}
{($_ -is [String]) -and ($_[0] -eq '=')} {
#region Save an Excel formula
$TargetCell.Formula = $_
if ($setNumformat) {$targetCell.Style.Numberformat.Format = $Numberformat }
#Write-Verbose "Cell '$Row`:$ColumnIndex' header '$Name' add value '$_' as formula"
break
}
@@ -481,12 +474,18 @@
#Write-Verbose "Cell '$Row`:$ColumnIndex' header '$Name' add value '$($_.AbsoluteUri)' as Hyperlink"
break
}
{(($NoNumberConversion) -and ($NoNumberConversion -contains $Name)) -or
($NoNumberConversion -eq '*')} {
#Save text without it to converting to number
$TargetCell.Value = $_
#Write-Verbose "Cell '$Row`:$ColumnIndex' header '$Name' add value '$($TargetCell.Value)' unconverted"
break
}
Default {
#Save a value as a number if possible
$number = $null
if ([Double]::TryParse( $_ , [ref]$number)) {
#was [Double]::TryParse([String]$_, [System.Globalization.NumberStyles]::Any,[System.Globalization.NumberFormatInfo]::CurrentInfo, [Ref]$number)) {
if ( [Double]::TryParse([String]$_, [System.Globalization.NumberStyles]::Any, [System.Globalization.NumberFormatInfo]::CurrentInfo, [Ref]$number)) {
# as simpler version using [Double]::TryParse( $_ , [ref]$number)) was found to cause problems reverted back to the longer version
$TargetCell.Value = $number
if ($setNumformat) {$targetCell.Style.Numberformat.Format = $Numberformat }
#Write-Verbose "Cell '$Row`:$ColumnIndex' header '$Name' add value '$($TargetCell.Value)' as number converted from '$_' with format '$Numberformat'"
@@ -629,6 +628,7 @@
$ColumnIndex += 1
#endregion
}
$ColumnIndex -= 1 # column index will be the last column whether isDataTypeValueType was true or false
}
}
Catch {
@@ -638,6 +638,20 @@
}
End {
if ($firstTimeThru) {
$LastRow = $ws.Dimension.End.Row
$LastCol = $ws.Dimension.End.Column
$endAddress = $ws.Dimension.End.Address
}
else {
$LastRow = $Row
$LastCol = $ColumnIndex
$endAddress = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R[$LastRow]C[$LastCol]", 0, 0)
}
$startAddress = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R[$StartRow]C[$StartColumn]", 0, 0)
$dataRange = "{0}:{1}" -f $startAddress, $endAddress
Write-Debug "Data Range '$dataRange'"
if ($AutoNameRange) {
Try {
if (-not $script:header) {
@@ -657,10 +671,10 @@
#, but start.column is the first populated one and .Columns is the count of populated ones.
# if we have 5 columns from 3 to 8, headers are numbered 0..4, so that is in the for loop and used for getting the name...
# but we have to add the start column on when referencing positions
foreach ($c in 0..($ws.Dimension.Columns - 1)) {
foreach ($c in 0..($LastCol - $StartColumn)) {
$targetRangeName = $script:Header[$c] -replace '\W' , '_'
$targetColumn = $c + $StartColumn
$theRange = $ws.Cells[$targetRow, $targetColumn, $ws.Dimension.End.Row , $targetColumn ]
$theRange = $ws.Cells[$targetRow, $targetColumn, $LastRow , $targetColumn ]
if ($ws.names[$targetRangeName]) { $ws.names[$targetRangeName].Address = $theRange.FullAddressAbsolute }
else {$ws.Names.Add($targetRangeName, $theRange) | Out-Null }
@@ -671,19 +685,9 @@
}
Catch {Write-Warning -Message "Failed adding named ranges to worksheet '$WorkSheetname': $_" }
}
try {
if ($Title) {
$startAddress = $ws.Dimension.Start.address -replace "$($ws.Dimension.Start.row)`$", "$($ws.Dimension.Start.row + 1)"
}
else {
$startAddress = $ws.Dimension.Start.Address
}
$dataRange = "{0}:{1}" -f $startAddress, $ws.Dimension.End.Address
Write-Debug "Data Range '$dataRange'"
if (-not [String]::IsNullOrEmpty($RangeName)) {
if ($RangeName) {
try {
if ($RangeName -match "\W") {
Write-Warning -Message "At least one character in $RangeName is illegal in a range name and will be replaced with '_' . "
$RangeName = $RangeName -replace '\W', '_'
@@ -692,66 +696,28 @@
if ($ws.Names[$RangeName]) { $ws.Names[$rangename].Address = $ws.Cells[$dataRange].FullAddressAbsolute }
else {$ws.Names.Add($RangeName, $ws.Cells[$dataRange]) | Out-Null }
}
Catch { Write-Warning -Message "Failed adding range '$RangeName' to worksheet '$WorkSheetname': $_" }
}
Catch { Write-Warning -Message "Failed adding range '$RangeName' to worksheet '$WorkSheetname': $_" }
if (-not [String]::IsNullOrEmpty($TableName)) {
try {
$csr = $StartRow
$csc = $StartColumn
$cer = $ws.Dimension.End.Row
$cec = $ws.Dimension.End.Column # was $script:Header.Count
if ($TableName) {
try {
if ($TableName -match "\W") {
Write-Warning -Message "At least one character in $TableName is illegal in a table name and will be replaced with '_' . "
$TableName = $TableName -replace '\W', '_'
}
$targetRange = $ws.Cells[$csr, $csc, $cer, $cec]
#if the table exists, update it.
if ($ws.Tables[$TableName]) {
$ws.Tables[$TableName].TableXml.table.ref = $targetRange.Address
$ws.Tables[$TableName].TableXml.table.ref = $dataRange
$ws.Tables[$TableName].TableStyle = $TableStyle
}
else {
$tbl = $ws.Tables.Add($targetRange, $TableName)
$tbl = $ws.Tables.Add($ws.Cells[$dataRange], $TableName)
$tbl.TableStyle = $TableStyle
}
Write-Verbose -Message "Defined table '$TableName' at $($targetRange.Address)"
}
catch {Write-Warning -Message "Failed adding table '$TableName' to worksheet '$WorkSheetname': $_"}
}
if ($PivotTableDefinition) {
foreach ($item in $PivotTableDefinition.GetEnumerator()) {
$params = $item.value
if ($params.keys -notcontains "SourceRange" -and
($params.Keys -notcontains "SourceWorkSheet" -or $params.SourceWorkSheet -eq $WorkSheetname)) {$params.SourceRange = $dataRange}
if ($params.Keys -notcontains "SourceWorkSheet") {$params.SourceWorkSheet = $ws }
if ($params.Keys -notcontains "NoTotalsInPivot" -and $NoTotalsInPivot ) {$params.NoTotalsInPivot = $true}
if ($params.Keys -notcontains "PivotDataToColumn" -and $PivotDataToColumn) {$params.PivotDataToColumn = $true}
Add-PivotTable -ExcelPackage $pkg -PivotTableName $item.key @Params
}
}
if ($IncludePivotTable -or $IncludePivotChart) {
$params = @{
"SourceRange" = $dataRange
}
if ($PivotTableName) {$params.PivotTableName = $PivotTableName}
else {$params.PivotTableName = $WorkSheetname + 'PivotTable'}
if ($PivotFilter) {$params.PivotFilter = $PivotFilter}
if ($PivotRows) {$params.PivotRows = $PivotRows}
if ($PivotColumns) {$Params.PivotColumns = $PivotColumns}
if ($PivotData) {$Params.PivotData = $PivotData}
if ($NoTotalsInPivot) {$params.NoTotalsInPivot = $true}
if ($PivotDataToColumn) {$params.PivotDataToColumn = $true}
if ($IncludePivotChart) {
$params.IncludePivotChart = $true
$Params.ChartType = $ChartType
if ($ShowCategory) {$params.ShowCategory = $true}
if ($ShowPercent) {$params.ShowPercent = $true}
if ($NoLegend) {$params.NoLegend = $true}
}
Add-PivotTable -ExcelPackage $pkg -SourceWorkSheet $ws @params
}
if ($AutoFilter) {
try {
@@ -761,6 +727,40 @@
catch {Write-Warning -Message "Failed adding autofilter to worksheet '$WorkSheetname': $_"}
}
if ($PivotTableDefinition) {
foreach ($item in $PivotTableDefinition.GetEnumerator()) {
$params = $item.value
if ($params.keys -notcontains "SourceRange" -and
($params.Keys -notcontains "SourceWorkSheet" -or $params.SourceWorkSheet -eq $WorkSheetname)) {$params.SourceRange = $dataRange}
if ($params.Keys -notcontains "SourceWorkSheet") {$params.SourceWorkSheet = $ws }
if ($params.Keys -notcontains "NoTotalsInPivot" -and $NoTotalsInPivot ) {$params.NoTotalsInPivot = $true}
if ($params.Keys -notcontains "PivotDataToColumn" -and $PivotDataToColumn) {$params.PivotDataToColumn = $true}
Add-PivotTable -ExcelPackage $pkg -PivotTableName $item.key @Params
}
}
if ($IncludePivotTable -or $IncludePivotChart) {
$params = @{
"SourceRange" = $dataRange
}
if ($PivotTableName) {$params.PivotTableName = $PivotTableName}
else {$params.PivotTableName = $WorkSheetname + 'PivotTable'}
if ($PivotFilter) {$params.PivotFilter = $PivotFilter}
if ($PivotRows) {$params.PivotRows = $PivotRows}
if ($PivotColumns) {$Params.PivotColumns = $PivotColumns}
if ($PivotData) {$Params.PivotData = $PivotData}
if ($NoTotalsInPivot) {$params.NoTotalsInPivot = $true}
if ($PivotDataToColumn) {$params.PivotDataToColumn = $true}
if ($IncludePivotChart) {
$params.IncludePivotChart = $true
$Params.ChartType = $ChartType
if ($ShowCategory) {$params.ShowCategory = $true}
if ($ShowPercent) {$params.ShowPercent = $true}
if ($NoLegend) {$params.NoLegend = $true}
}
Add-PivotTable -ExcelPackage $pkg -SourceWorkSheet $ws @params
}
try {
if ($FreezeTopRow) {
$ws.View.FreezePanes(2, 1)
@@ -822,8 +822,8 @@
foreach ($chartDef in $ExcelChartDefinition) {
$params = @{}
$chardef.PSObject.Properties | ForEach-Object {if ($_.value -ne $null) {$params[$_.name] = $_.value}}
Add-ExcelChart $params
$chartDef.PSObject.Properties | ForEach-Object {if ($_.value -ne $null) {$params[$_.name] = $_.value}}
Add-ExcelChart -Worksheet $ws @params
}
foreach ($ct in $ConditionalText) {
@@ -842,7 +842,7 @@
if ($CellStyleSB) {
try {
$TotalRows = $ws.Dimension.Rows
$LastColumn = (Get-ExcelColumnName $ws.Dimension.Columns).ColumnName
$LastColumn = $ws.Dimension.Address -replace "^.*:(\w*)\d+$" , '$1'
& $CellStyleSB $ws $TotalRows $LastColumn
}
catch {Write-Warning -Message "Failed processing CellStyleSB in worksheet '$WorkSheetname': $_"}
@@ -1164,34 +1164,87 @@ function Add-PivotTable {
}
}
function Add-ExcelChart {
[cmdletbinding()]
param(
$Worksheet,
$Title = "Chart Title",
$Header,
[OfficeOpenXml.ExcelWorksheet]$Worksheet,
[String]$Title = "Chart Title",
#$Header, Not used but referenced previously
[OfficeOpenXml.Drawing.Chart.eChartType]$ChartType = "ColumnStacked",
$XRange,
$YRange,
$Width = 500,
$Height = 350,
$Row = 0,
$RowOffSetPixels = 10,
$Column = 6,
$ColumnOffSetPixels = 5,
[int]$Width = 500,
[int]$Height = 350,
[int]$Row = 0,
[int]$RowOffSetPixels = 10,
[int]$Column = 6,
[int]$ColumnOffSetPixels = 5,
[OfficeOpenXml.Drawing.Chart.eLegendPosition]$LegendPostion,
$LegendSize,
[Switch]$legendBold,
[Switch]$NoLegend,
[Switch]$ShowCategory,
[Switch]$ShowPercent,
$SeriesHeader
)
$SeriesHeader,
[Switch]$TitleBold,
[Int]$TitleSize ,
[String]$XAxisTitleText,
[Switch]$XAxisTitleBold,
$XAxisTitleSize ,
[string]$XAxisNumberformat,
$XMajorUnit,
$XMinorUnit,
$XMaxValue,
$XMinValue,
[OfficeOpenXml.Drawing.Chart.eAxisPosition]$XAxisPosition ,
[String]$YAxisTitleText,
[Switch]$YAxisTitleBold,
$YAxisTitleSize,
[string]$YAxisNumberformat,
$YMajorUnit,
$YMinorUnit,
$YMaxValue,
$YMinValue,
[OfficeOpenXml.Drawing.Chart.eAxisPosition]$YAxisPosition )
try {
$ChartName = 'Chart' + (Split-Path -Leaf ([System.IO.path]::GetTempFileName())) -replace 'tmp|\.', ''
$chart = $Worksheet.Drawings.AddChart($ChartName, $ChartType)
$chart.Title.Text = $Title
if ($TitleBold) {$chart.Title.Font.Bold = $true}
if ($TitleSize) {$chart.Title.Font.Size = $TitleSize}
if ($NoLegend) { $chart.Legend.Remove() }
else {
if ($LegendPostion) {$Chart.Legend.Position = $LegendPostion}
if ($LegendSize) {$chart.Legend.Font.Size = $LegendSize}
if ($legendBold) {$chart.Legend.Font.Bold = $true}
}
if ($XAxisTitleText) {
$chart.XAxis.Title.Text = $XAxisTitleText
if ($XAxisTitleBold) {$chart.XAxis.Title.Font.Bold = $true}
if ($XAxisTitleSize) {$chart.XAxis.Title.Font.Size = $XAxisTitleSize}
}
if ($XAxisPosition) {$chart.XAxis.AxisPosition = $XAxisPosition}
if ($XMajorUnit) {$chart.XAxis.MajorUnit = $XMajorUnit}
if ($XMinorUnit) {$chart.XAxis.MinorUnit = $XMinorUnit}
if ($XMinValue -ne $null) {$chart.XAxis.MinValue = $XMinValue}
if ($XMaxValue -ne $null) {$chart.XAxis.MaxValue = $XMaxValue}
if ($XAxisNumberformat) {$chart.XAxis.Format = $XAxisNumberformat}
if ($YAxisTitleText) {
$chart.YAxis.Title.Text = $YAxisTitleText
if ($YAxisTitleBold) {$chart.YAxis.Title.Font.Bold = $true}
if ($YAxisTitleSize) {$chart.YAxis.Title.Font.Size = $YAxisTitleSize}
}
if ($YAxisPosition) {$chart.YAxis.AxisPosition = $YAxisPosition}
if ($YMajorUnit) {$chart.YAxis.MajorUnit = $YMajorUnit}
if ($YMinorUnit) {$chart.YAxis.MinorUnit = $YMinorUnit}
if ($YMinValue-ne $null) {$chart.YAxis.MinValue = $YMinValue}
if ($YMaxValue-ne $null) {$chart.YAxis.MaxValue = $YMaxValue}
if ($YAxisNumberformat) {$chart.YAxis.Format = $YAxisNumberformat}
if ($chart.Datalabel -ne $null) {
$chart.Datalabel.ShowCategory = [boolean]$ShowCategory
$chart.Datalabel.ShowPercent = [boolean]$ShowPercent
$chart.Datalabel.ShowPercent = [boolean]$ShowPercent
}
$chart.SetPosition($Row, $RowOffsetPixels, $Column, $ColumnOffsetPixels)
@@ -1201,13 +1254,13 @@ function Add-ExcelChart {
if ($chartDefCount -eq 1) {
$Series = $chart.Series.Add($YRange, $XRange)
if ($SeriesHeader) { $Series.Header = $SeriesHeader}
else { $Series.Header = 'Series 1'}
else { $Series.Header = 'Series 1'}
}
else {
for ($idx = 0; $idx -lt $chartDefCount; $idx += 1) {
$Series = $chart.Series.Add($YRange[$idx], $XRange)
if ($SeriesHeader.Count -gt 0) { $Series.Header = $SeriesHeader[$idx] }
else { $Series.Header = "Series $($idx)"}
else { $Series.Header = "Series $($idx)"}
}
}
}

View File

@@ -1,7 +1,7 @@
function Get-XYRange {
param($targetData)
$record = $targetData| select -First 1
$record = $targetData| Select-Object -First 1
$p=$record.psobject.Properties.name
$infer = for ($idx = 0; $idx -lt $p.Count; $idx++) {
@@ -15,12 +15,12 @@ function Get-XYRange {
Name = $name
Value = $value
DataType = $result.DataType
ExcelColumn = (Get-ExcelColumnName ($idx+1)).ColumnName
ExcelColumn = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R[1]C[$($idx+1)]", 0 , 0) -replace "\d+", "" #(Get-ExcelColumnName ($idx + 1)).ColumnName
}
}
[PSCustomObject]@{
XRange = $infer | ? {$_.datatype -match 'string'} | select -First 1 excelcolumn, name
YRange = $infer | ? {$_.datatype -match 'int|double'} |select -First 1 excelcolumn, name
XRange = $infer | ? {$_.datatype -match 'string'} | Select-Object -First 1 excelcolumn, name
YRange = $infer | ? {$_.datatype -match 'int|double'} |Select-Object -First 1 excelcolumn, name
}
}

View File

@@ -1,37 +1,38 @@
function New-ExcelChart {
function New-ExcelChartDefinition {
[cmdletbinding()]
[Alias("New-ExcelChart")] #This was the former name. The new name reflects that we are defining a chart, not making one in the workbook.
param(
$Title="Chart Title",
$Title = "Chart Title",
$Header,
[OfficeOpenXml.Drawing.Chart.eChartType]$ChartType="ColumnStacked",
[OfficeOpenXml.Drawing.Chart.eChartType]$ChartType = "ColumnStacked",
$XRange,
$YRange,
$Width=500,
$Height=350,
$Row=0,
$RowOffSetPixels=10,
$Column=6,
$ColumnOffSetPixels=5,
$Width = 500,
$Height = 350,
$Row = 0,
$RowOffSetPixels = 10,
$Column = 6,
$ColumnOffSetPixels = 5,
[Switch]$NoLegend,
[Switch]$ShowCategory,
[Switch]$ShowPercent,
$SeriesHeader
)
if ( $Header ) {Write-Warning "The header parameter is ignored."} #Nothing was done with it when creating a chart.
[PSCustomObject]@{
Title=$Title
Header=$Header
ChartType=$ChartType
XRange=$XRange
YRange=$YRange
Width=$Width
Height=$Height
Row=$Row
RowOffSetPixels=$RowOffSetPixels
Column=$Column
ColumnOffSetPixels=$ColumnOffSetPixels
NoLegend = if($NoLegend) {$true} else {$false}
ShowCategory = if($ShowCategory) {$true} else {$false}
ShowPercent = if($ShowPercent) {$true} else {$false}
SeriesHeader=$SeriesHeader
}
Title = $Title
ChartType = $ChartType
XRange = $XRange
YRange = $YRange
Width = $Width
Height = $Height
Row = $Row
RowOffSetPixels = $RowOffSetPixels
Column = $Column
ColumnOffSetPixels = $ColumnOffSetPixels
NoLegend = $NoLegend -as [Boolean]
ShowCategory = $ShowCategory-as [Boolean]
ShowPercent = $ShowPercent -as [Boolean]
SeriesHeader = $SeriesHeader
}
}

931
README.md

File diff suppressed because it is too large Load Diff

View File

@@ -1,52 +1,56 @@
#Requires -Modules Pester
describe "Compare Worksheet" {
# $here = Split-Path -Parent $MyInvocation.MyCommand.Path
# Import-Module $here -Force -Verbose
Import-Module $PSScriptRoot\..\ImportExcel.psd1 -Force
Remove-Item "$env:temp\server*.xlsx"
Describe "Compare Worksheet" {
Remove-Item -Path "$env:temp\server*.xlsx"
[System.Collections.ArrayList]$s = get-service | Select-Object -Property *
$s | Export-Excel -Path $env:temp\server1.xlsx
$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
#$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"
$s[2].DisplayName = "Changed from the orginal"
$d = $s[-1] | Select-Object -Property *
$d.DisplayName = "Dummy Service"
$d.Name = "Dummy"
$s.Insert(3,$d)
$d = $s[-1] | Select-Object -Property *
$d.DisplayName = "Dummy Service"
$d.Name = "Dummy"
$s.Insert(3,$d)
$row6Name = $s[5].name
$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"
$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" | Sort-Object -Property _row, _file
Context "Simple comparison output" {
it "Found the right number of differences " {
$comp | should not beNullOrEmpty
$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"
$comp | should not beNullOrEmpty
$comp[0]._Side | should not be $comp[1]._Side
$comp[0]._Row | should be 4
$comp[1]._Row | should be 4
$comp[1].Name | should be $comp[0].Name
$comp[0].DisplayName | should be $row4Displayname
$comp[1].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 | 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 | should not beNullOrEmpty
$comp[3]._Side | should be '<='
$comp[3]._Row | should be 6
$comp[3].Name | should be $row6Name
}
}
@@ -66,20 +70,20 @@ describe "Compare Worksheet" {
}
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
$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
$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"
@@ -90,69 +94,67 @@ describe "Compare Worksheet" {
$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
$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
[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
#$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"
$s[2].DisplayName = "Changed from the orginal"
$d = $s[-1] | Select-Object -Property *
$d.DisplayName = "Dummy Service"
$d.ServiceName = "Dummy"
$s.Insert(3,$d)
$d = $s[-1] | Select-Object -Property *
$d.DisplayName = "Dummy Service"
$d.ServiceName = "Dummy"
$s.Insert(3,$d)
$row6Name = $s[5].ServiceName
$row6Name = $s[5].ServiceName
$s.RemoveAt(5)
$s[10].ServiceType = "Changed should not matter"
$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
$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 | Sort-Object _row,_file
$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 " {
Context "More complex comparison: output check and different worksheet names " {
it "Found the right number of differences " {
$comp | should not beNullOrEmpty
$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"
$comp | should not beNullOrEmpty
$comp[0]._Side | should not be $comp[1]._Side
$comp[0]._Row | should be 4
$comp[1]._Row | should be 4
$comp[1].ServiceName | should be $comp[0].ServiceName
$comp[0].DisplayName | should be $row4Displayname
$comp[1].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 | 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 | should not beNullOrEmpty
$comp[3]._Side | should be '<='
$comp[3]._Row | should be 6
$comp[3].ServiceName | should be $row6Name
}
@@ -161,22 +163,22 @@ describe "Compare Worksheet" {
$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"
$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
$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
}
}

View File

@@ -0,0 +1,694 @@
#Requires -Modules Pester
# $here = Split-Path -Parent $MyInvocation.MyCommand.Path
# Import-Module $here -Force -Verbose
Import-Module $PSScriptRoot\..\ImportExcel.psd1 -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
}
it "Started Excel to display the file " {
Get-process -Name Excel, xlim -ErrorAction SilentlyContinue | Should not benullorempty
}
Start-Sleep -Seconds 5 ;
#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
}
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 $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
}
}
Context " # Chart from MultiSeries.ps1 in the Examples\charts Directory" {
$path = "$env:TEMP\Test.xlsx"
Remove-Item -Path $path -ErrorAction SilentlyContinue
$data = invoke-sum (Get-Process) Company Handles, PM, VirtualMemorySize
it "used Invoke-Sum to create a data set " {
$data | Should not beNullOrEmpty
$data.count | Should beGreaterThan 1
$data[1].Name | Should not beNullOrEmpty
$data[1].Handles | Should not beNullOrEmpty
$data[1].PM | Should not beNullOrEmpty
$data[1].VirtualMemorySize | Should not beNullOrEmpty
}
$c = New-ExcelChartDefinition -Title Stats -ChartType LineMarkersStacked -XRange "Processes[Name]" -YRange "Processes[PM]", "Processes[VirtualMemorySize]" -SeriesHeader 'PM', 'VMSize'
it "Created the Excel chart definition " {
$c | Should not beNullOrEmpty
$c.ChartType.gettype().name | Should be "eChartType"
$c.ChartType.tostring() | Should be "LineMarkersStacked"
$c.yrange -is [array] | Should be $true
$c.yrange.count | Should be 2
$c.yrange[0] | Should be "Processes[PM]"
$c.yrange[1] | Should be "Processes[VirtualMemorySize]"
$c.xrange | Should be "Processes[Name]"
$c.Title | Should be "Stats"
$c.Nolegend | Should not be $true
$c.ShowCategory | Should not be $true
$c.ShowPercent | Should not be $true
}
$data | Export-Excel $path -AutoSize -TableName Processes -ExcelChartDefinition $c
$excel = Open-ExcelPackage -Path $path
$drawings = $excel.Workbook.Worksheets[1].drawings
it "Used the Excel chart definition with Export-Excel " {
$drawings.count | Should be 1
$drawings[0].ChartType | Should be "LineMarkersStacked"
$drawings[0].Series.count | Should be 2
$drawings[0].Series[0].Series | Should be "'Sheet1'!Processes[PM]"
$drawings[0].Series[0].XSeries | Should be "'Sheet1'!Processes[Name]"
$drawings[0].Series[1].Series | Should be "'Sheet1'!Processes[VirtualMemorySize]"
$drawings[0].Series[1].XSeries | Should be "'Sheet1'!Processes[Name]"
$drawings[0].Title.text | Should be "Stats"
}
Close-ExcelPackage $excel
}
Context " # variation of plot.ps1 from Examples Directory using Add chart outside ExportExcel" {
$path = "$env:TEMP\Test.xlsx"
$excel = 0..360 | ForEach-Object {[pscustomobject][ordered]@{x = $_; Sinx = "=Sin(Radians(x)) "}} | Export-Excel -AutoNameRange -Path $path -WorkSheetname SinX -ClearSheet -PassThru
Add-ExcelChart -Worksheet $excel.Workbook.Worksheets["Sinx"] -XRange "X" -YRange "Sinx" -Title "Graph of Sine X" -ChartType line -SeriesHeader "Sin(x)" -Column 2 -ColumnOffSetPixels 35 -TitleBold -TitleSize 14 -XAxisTitleText "Degrees" -XAxisTitleBold -XAxisTitleSize 12 -XMajorUnit 30 -XMinorUnit 10 -XMinValue 0 -XMaxValue 361 -Width 800 -YMinValue -1.25 -YMaxValue 1.25 -YMajorUnit 0.25 -YAxisNumberformat "0.00" -LegendPostion Bottom -LegendSize 8 -legendBold
$d = $excel.Workbook.Worksheets["Sinx"].Drawings[0]
It "Controled the axes and title and legend of the chart" {
$d.XAxis.MaxValue | Should be 361
$d.XAxis.MajorUnit | Should be 30
$d.XAxis.MinorUnit | Should be 10
$d.XAxis.Title.Text | Should be "degrees"
$d.XAxis.Title.Font.bold | Should be $true
$d.XAxis.Title.Font.Size | Should be 12
$d.XAxis.MajorUnit | Should be 30
$d.XAxis.MinorUnit | Should be 10
$d.XAxis.MinValue | Should be 0
$d.XAxis.MaxValue | Should be 361
$d.YAxis.Format | Should be "0.00"
$d.Title.Text | Should be "Graph of Sine X"
$d.Title.Font.Bold | Should be $true
$d.Title.Font.Size | Should be 14
$d.yAxis.MajorUnit | Should be 0.25
$d.yAxis.MaxValue | Should be 1.25
$d.yaxis.MinValue | Should be -1.25
$d.Legend.Position.ToString() | Should be "Bottom"
$d.Legend.Font.Bold | Should be $true
$d.Legend.Font.Size | Should be 8
$d.ChartType.tostring() | Should be "line"
$d.From.Column | Should be 2
}
Close-ExcelPackage -ExcelPackage $excel -nosave
}
## To do
## More Charts , pivot options & other FreezePanes settings ?
## Style script block
## Rezip ?
}

View File

@@ -1,53 +1,53 @@
Function Compare-WorkSheet {
<#
.Synopsis
Compares two worksheets with the same name in different files.
.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.
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 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
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
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
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
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.
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
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.
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
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
#First file to compare
[parameter(Mandatory=$true,Position=0)]
$Referencefile ,
#Second file to compare
@@ -57,106 +57,106 @@ Function Compare-WorkSheet {
$WorkSheetName = "Sheet1",
#Properties to include in the DIFF - supports wildcards, default is "*"
$Property = "*" ,
#Properties to exclude from the the search - supports wildcards
#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,
[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,
[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.
[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
#If specified, highlights the DIFF rows
[System.Drawing.Color]$BackgroundColor,
#If specified identifies the tabs which contain DIFF rows (ignored if -backgroundColor is omitted)
#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"
#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.
#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)
#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
#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
#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
#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.
#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.
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"
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]}
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 }
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
$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.
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}) }
#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
$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
#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 ++)
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 "_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
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 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
#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}
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[$_]
$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
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
Set-Format -WorkSheet $ws -Range $range -BackgroundColor $BackgroundColor
}
if ($TabColor) {
foreach ($tab in ($file.group._sheet | Select-Object -Unique)) {
@@ -166,12 +166,12 @@ Function Compare-WorkSheet {
$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 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}
$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}
if ($oneFile ) {$xl2 = $xl1}
else {$xl2 = Open-ExcelPackage -path $Differencefile }
foreach ($u in $updates) {
foreach ($p in $propList) {
@@ -185,337 +185,76 @@ Function Compare-WorkSheet {
}
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
}
}
Set-Format -WorkSheet $ws2 -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." }
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 ($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 ($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
$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
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 }
#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]@{}
$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 }
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 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
#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" } }
$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" }
$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 (=>)"
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 ($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 }
# }

Binary file not shown.

Binary file not shown.

Binary file not shown.