Merge pull request #458 from jhoneill/master

Fixed #457 & a couple more tweaks
This commit is contained in:
Doug Finke
2018-10-08 17:05:41 -04:00
committed by GitHub
8 changed files with 191 additions and 154 deletions

View File

@@ -404,12 +404,13 @@ function Import-Excel {
else { else {
#region Create one object per row #region Create one object per row
foreach ($R in $Rows) { foreach ($R in $Rows) {
Write-Verbose "Import row '$R'" #Disabled write-verbose for speed
# Write-Verbose "Import row '$R'"
$NewRow = [Ordered]@{} $NewRow = [Ordered]@{}
foreach ($P in $PropertyNames) { foreach ($P in $PropertyNames) {
$NewRow[$P.Value] = $Worksheet.Cells[$R, $P.Column].Value $NewRow[$P.Value] = $Worksheet.Cells[$R, $P.Column].Value
Write-Verbose "Import cell '$($Worksheet.Cells[$R, $P.Column].Address)' with property name '$($p.Value)' and value '$($Worksheet.Cells[$R, $P.Column].Value)'." # Write-Verbose "Import cell '$($Worksheet.Cells[$R, $P.Column].Address)' with property name '$($p.Value)' and value '$($Worksheet.Cells[$R, $P.Column].Value)'."
} }
[PSCustomObject]$NewRow [PSCustomObject]$NewRow

View File

@@ -1,25 +1,25 @@
Function Merge-Worksheet { Function Merge-Worksheet {
<# <#
.Synopsis .Synopsis
Merges two worksheets (or other objects) into a single worksheet with differences marked up. Merges two Worksheets (or other objects) into a single Worksheet with differences marked up.
.Description .Description
The Compare-Worksheet command takes two worksheets and marks differences in the source document, and optionally outputs a grid showing the changes. The Compare-Worksheet command takes two Worksheets and marks differences in the source document, and optionally outputs a grid showing the changes.
By contrast the Merge-Worksheet command takes the worksheets and combines them into a single sheet showing the old and new data side by side . By contrast the Merge-Worksheet command takes the Worksheets and combines them into a single sheet showing the old and new data side by side .
Although it is designed to work with Excel data it can work with arrays of any kind of object; so it can be a merge *of* worksheets, or a merge *to* worksheet. Although it is designed to work with Excel data it can work with arrays of any kind of object; so it can be a merge *of* Worksheets, or a merge *to* Worksheet.
.Example .Example
merge-worksheet "Server54.xlsx" "Server55.xlsx" -WorkSheetName services -OutputFile Services.xlsx -OutputSheetName 54-55 -show merge-Worksheet "Server54.xlsx" "Server55.xlsx" -WorksheetName services -OutputFile Services.xlsx -OutputSheetName 54-55 -show
The workbooks contain audit information for two servers, one page contains a list of services. This command creates a worksheet named 54-55 The workbooks contain audit information for two servers, one page contains a list of services. This command creates a Worksheet named 54-55
in a workbook named services which shows all the services and their differences, and opens it in Excel. in a workbook named services which shows all the services and their differences, and opens it in Excel.
.Example .Example
merge-worksheet "Server54.xlsx" "Server55.xlsx" -WorkSheetName services -OutputFile Services.xlsx -OutputSheetName 54-55 -HideEqual -AddBackgroundColor LightBlue -show merge-Worksheet "Server54.xlsx" "Server55.xlsx" -WorksheetName services -OutputFile Services.xlsx -OutputSheetName 54-55 -HideEqual -AddBackgroundColor LightBlue -show
This modifies the previous command to hide the equal rows in the output sheet and changes the color used to mark rows added to the second file. This modifies the previous command to hide the equal rows in the output sheet and changes the color used to mark rows added to the second file.
.Example .Example
merge-worksheet -OutputFile .\j1.xlsx -OutputSheetName test11 -ReferenceObject (dir .\ImportExcel\4.0.7) -DifferenceObject (dir .\ImportExcel\4.0.8) -Property Length -Show merge-Worksheet -OutputFile .\j1.xlsx -OutputSheetName test11 -ReferenceObject (dir .\ImportExcel\4.0.7) -DifferenceObject (dir .\ImportExcel\4.0.8) -Property Length -Show
This version compares two directories, and marks what has changed. This version compares two directories, and marks what has changed.
Because no "Key" property is given, "Name" is assumed to be the key and the only other property examined is length. Because no "Key" property is given, "Name" is assumed to be the key and the only other property examined is length.
Files which are added or deleted or have changed size will be highlighed in the output sheet. Changes to dates or other attributes will be ignored. Files which are added or deleted or have changed size will be highlighed in the output sheet. Changes to dates or other attributes will be ignored.
.Example .Example
merge-worksheet -RefO (dir .\ImportExcel\4.0.7) -DiffO (dir .\ImportExcel\4.0.8) -Pr Length | Out-GridView merge-Worksheet -RefO (dir .\ImportExcel\4.0.7) -DiffO (dir .\ImportExcel\4.0.8) -Pr Length | Out-GridView
This time no file is written and the results -which include all properties, not just length, are output and sent to Out-Gridview. This time no file is written and the results -which include all properties, not just length, are output and sent to Out-Gridview.
This version uses aliases to shorten the parameters, This version uses aliases to shorten the parameters,
(OutputFileName can be "outFile" and the sheet "OutSheet" : DifferenceObject & ReferenceObject can be DiffObject & RefObject). (OutputFileName can be "outFile" and the sheet "OutSheet" : DifferenceObject & ReferenceObject can be DiffObject & RefObject).
@@ -27,58 +27,70 @@
[cmdletbinding(SupportsShouldProcess=$true)] [cmdletbinding(SupportsShouldProcess=$true)]
Param( Param(
#First Excel file to compare. You can compare two Excel files or two other objects but not one of each. #First Excel file to compare. You can compare two Excel files or two other objects but not one of each.
[parameter(ParameterSetName='A',Mandatory=$true,Position=0)] [parameter(ParameterSetName='A',Mandatory=$true,Position=0)] #A = Compare two files default headers
[parameter(ParameterSetName='B',Mandatory=$true,Position=0)] [parameter(ParameterSetName='B',Mandatory=$true,Position=0)] #B = Compare two files user supplied headers
[parameter(ParameterSetName='C',Mandatory=$true,Position=0)] [parameter(ParameterSetName='C',Mandatory=$true,Position=0)] #C = Compare two files headers P1, P2, P3 etc
$Referencefile , $Referencefile ,
#Second Excel file to compare. #Second Excel file to compare.
[parameter(ParameterSetName='A',Mandatory=$true,Position=1)] [parameter(ParameterSetName='A',Mandatory=$true,Position=1)]
[parameter(ParameterSetName='B',Mandatory=$true,Position=1)] [parameter(ParameterSetName='B',Mandatory=$true,Position=1)]
[parameter(ParameterSetName='C',Mandatory=$true,Position=1)] [parameter(ParameterSetName='C',Mandatory=$true,Position=1)]
[parameter(ParameterSetName='E',Mandatory=$true,Position=1)] [parameter(ParameterSetName='E',Mandatory=$true,Position=1)] #D Compat two objects; E = Compare one object one file that uses default headers
[parameter(ParameterSetName='F',Mandatory=$true,Position=1)] #F = Compare one object one file that uses user supplied headers
[parameter(ParameterSetName='G',Mandatory=$true,Position=1)] #G Compare one object one file that uses headers P1, P2, P3 etc
$Differencefile , $Differencefile ,
#Name(s) of worksheets to compare, #Name(s) of Worksheets to compare,
[parameter(ParameterSetName='A',Position=2)] [parameter(ParameterSetName='A',Position=2)] #Applies to all sets EXCEPT D which is two objects (no sheets)
[parameter(ParameterSetName='B',Position=2)] [parameter(ParameterSetName='B',Position=2)]
[parameter(ParameterSetName='C',Position=2)] [parameter(ParameterSetName='C',Position=2)]
[parameter(ParameterSetName='E',Position=2)] [parameter(ParameterSetName='E',Position=2)]
$WorkSheetName = "Sheet1", [parameter(ParameterSetName='F',Position=2)]
[parameter(ParameterSetName='G',Position=2)]
$WorksheetName = "Sheet1",
#The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row. #The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row.
[parameter(ParameterSetName='A')] [parameter(ParameterSetName='A')] #Applies to all sets EXCEPT D which is two objects (no sheets, so no start row )
[parameter(ParameterSetName='B')] [parameter(ParameterSetName='B')]
[parameter(ParameterSetName='C')] [parameter(ParameterSetName='C')]
[parameter(ParameterSetName='E')] [parameter(ParameterSetName='E')]
[parameter(ParameterSetName='F')]
[parameter(ParameterSetName='G')]
[int]$Startrow = 1, [int]$Startrow = 1,
#Specifies custom property names to use, instead of the values defined in the column headers of the TopRow. #Specifies custom property names to use, instead of the values defined in the column headers of the TopRow.
[Parameter(ParameterSetName='B',Mandatory=$true)] [Parameter(ParameterSetName='B',Mandatory=$true)] #Compare object + sheet or 2 sheets with user supplied headers
[Parameter(ParameterSetName='F',Mandatory=$true)]
[String[]]$Headername, [String[]]$Headername,
#Automatically generate property names (P1, P2, P3, ..) instead of the using the values the top row of the sheet. #Automatically generate property names (P1, P2, P3, ..) instead of the using the values the top row of the sheet.
[Parameter(ParameterSetName='C',Mandatory=$true)] [Parameter(ParameterSetName='C',Mandatory=$true)] #Compare object + sheet or 2 sheets with headers of P1, P2, P3 ...
[Parameter(ParameterSetName='G',Mandatory=$true)]
[switch]$NoHeader, [switch]$NoHeader,
#Object to compare if a worksheet is NOT being used. #Reference object to compare if a Worksheet is NOT being used. Reference object can combine with a difference sheet or difference object
[parameter(ParameterSetName='D',Mandatory=$true)] [parameter(ParameterSetName='D',Mandatory=$true)]
[parameter(ParameterSetName='E',Mandatory=$true)] [parameter(ParameterSetName='E',Mandatory=$true)]
[parameter(ParameterSetName='F',Mandatory=$true)]
[parameter(ParameterSetName='G',Mandatory=$true)]
[Alias('RefObject')] [Alias('RefObject')]
$ReferenceObject , $ReferenceObject ,
#Object to compare if a worksheet is NOT being used. #Difference object to compare if a Worksheet is NOT being used for either half. Can't have a reference sheet and difference object.
[parameter(ParameterSetName='D',Mandatory=$true,Position=1)] [parameter(ParameterSetName='D',Mandatory=$true,Position=1)]
[Alias('DiffObject')] [Alias('DiffObject')]
$DifferenceObject , $DifferenceObject ,
[parameter(ParameterSetName='D',Position=2)] [parameter(ParameterSetName='D',Position=2)]
[parameter(ParameterSetName='E',Position=3)] [parameter(ParameterSetName='E',Position=2)]
[parameter(ParameterSetName='F',Position=2)]
[parameter(ParameterSetName='G',Position=2)]
#If there isn't a filename to use to label data from the "Difference" side, DiffPrefix is used, it defaults to "=>" #If there isn't a filename to use to label data from the "Difference" side, DiffPrefix is used, it defaults to "=>"
$DiffPrefix = "=>" , $DiffPrefix = "=>" ,
#File to hold merged data. #File to hold merged data.
[parameter(Position=3)] [parameter(Position=3)]
[Alias('OutFile')] [Alias('OutFile')]
$OutputFile , $OutputFile ,
#Name of worksheet to output - if none specified will use the reference worksheet name. #Name of Worksheet to output - if none specified will use the reference Worksheet name.
[parameter(Position=4)] [parameter(Position=4)]
[Alias('OutSheet')] [Alias('OutSheet')]
$OutputSheetName = "Sheet1", $OutputSheetName = "Sheet1",
@@ -110,30 +122,31 @@
try { $oneFile = ((Resolve-Path -Path $Referencefile -ErrorAction Stop).path -eq (Resolve-Path -Path $Differencefile -ErrorAction Stop).path)} 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 } Catch { Write-Warning -Message "Could not Resolve the filenames." ; return }
#If we have one file , we must have two different worksheet names. If we have two files $worksheetName can be a single string or two strings. #If we have one file , we must have two different Worksheet names. If we have two files $WorksheetName can be a single string or two strings.
if ($onefile -and ( ($WorkSheetName.count -ne 2) -or $WorkSheetName[0] -eq $WorkSheetName[1] ) ) { 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 return
} }
if ($WorkSheetName.count -eq 2) {$workSheet2 = $DiffPrefix = $WorkSheetName[1] ; $worksheet1 = $WorkSheetName[0] ; } if ($WorksheetName.count -eq 2) {$Worksheet2 = $DiffPrefix = $WorksheetName[1] ; $Worksheet1 = $WorksheetName[0] ; }
elseif ($WorkSheetName -is [string]) {$worksheet2 = $workSheet1 = $WorkSheetName ; elseif ($WorksheetName -is [string]) {$Worksheet2 = $Worksheet1 = $WorksheetName ;
$DiffPrefix = (Split-Path -Path $Differencefile -Leaf) -replace "\.xlsx$","" } $DiffPrefix = (Split-Path -Path $Differencefile -Leaf) -replace "\.xlsx$","" }
else {Write-Warning -Message "You must provide either a single worksheet name or two names." ; return } else {Write-Warning -Message "You must provide either a single Worksheet name or two names." ; return }
$params= @{ ErrorAction = [System.Management.Automation.ActionPreference]::Stop } $params= @{ ErrorAction = [System.Management.Automation.ActionPreference]::Stop }
foreach ($p in @("HeaderName","NoHeader","StartRow")) {if ($PSBoundParameters[$p]) {$params[$p] = $PSBoundParameters[$p]}} foreach ($p in @("HeaderName","NoHeader","StartRow")) {if ($PSBoundParameters[$p]) {$params[$p] = $PSBoundParameters[$p]}}
try { try {
$ReferenceObject = Import-Excel -Path $Referencefile -WorksheetName $WorkSheet1 @params $ReferenceObject = Import-Excel -Path $Referencefile -WorksheetName $Worksheet1 @params
$DifferenceObject = Import-Excel -Path $Differencefile -WorksheetName $WorkSheet2 @Params $DifferenceObject = Import-Excel -Path $Differencefile -WorksheetName $Worksheet2 @Params
} }
Catch {Write-Warning -Message "Could not read the worksheet from $Referencefile::$worksheet1 and/or $Differencefile::$worksheet2." ; return } Catch {Write-Warning -Message "Could not read the Worksheet from $Referencefile::$Worksheet1 and/or $Differencefile::$Worksheet2." ; return }
if ($NoHeader) {$firstDataRow = $Startrow } else {$firstDataRow = $Startrow + 1} if ($NoHeader) {$firstDataRow = $Startrow } else {$firstDataRow = $Startrow + 1}
} }
elseif ( $Differencefile) { elseif ( $Differencefile) {
if ($WorkSheetName -isnot [string]) {Write-Warning -Message "You must provide a single worksheet name." ; return } if ($WorksheetName -isnot [string]) {Write-Warning -Message "You must provide a single Worksheet name." ; return }
$params = @{WorkSheetName=$WorkSheetName; Path=$Differencefile; ErrorAction = [System.Management.Automation.ActionPreference]::Stop ;} $params = @{WorksheetName=$WorksheetName; Path=$Differencefile; ErrorAction=[System.Management.Automation.ActionPreference]::Stop }
foreach ($p in @("HeaderName","NoHeader","StartRow")) {if ($PSBoundParameters[$p]) {$params[$p] = $PSBoundParameters[$p]}}
try {$DifferenceObject = Import-Excel @Params } try {$DifferenceObject = Import-Excel @Params }
Catch {Write-Warning -Message "Could not read the worksheet '$WorkSheetName' from $Differencefile::$WorkSheetName." ; return } Catch {Write-Warning -Message "Could not read the Worksheet '$WorksheetName' from $Differencefile::$WorksheetName." ; return }
if ($DiffPrefix -eq "=>" ) { if ($DiffPrefix -eq "=>" ) {
$DiffPrefix = (Split-Path -Path $Differencefile -Leaf) -replace "\.xlsx$","" $DiffPrefix = (Split-Path -Path $Differencefile -Leaf) -replace "\.xlsx$",""
} }
@@ -149,7 +162,7 @@
$headings = $DifferenceObject[0].psobject.Properties.Name # This preserves the sequence - using get-member would sort them alphabetically! There may be extra properties in $headings = $DifferenceObject[0].psobject.Properties.Name # This preserves the sequence - using get-member would sort them alphabetically! There may be extra properties in
if ($NoHeader -and "Name" -eq $Key) {$Key = "p1"} if ($NoHeader -and "Name" -eq $Key) {$Key = "p1"}
if ($headings -notcontains $Key -and if ($headings -notcontains $Key -and
('*' -ne $Key)) {Write-Warning -Message "You need to specify one of the headings in the sheet '$worksheet1' as a key." ; return } ('*' -ne $Key)) {Write-Warning -Message "You need to specify one of the headings in the sheet '$Worksheet1' as a key." ; return }
foreach ($p in $Property) { $propList += ($headings.where({$_ -like $p}) )} foreach ($p in $Property) { $propList += ($headings.where({$_ -like $p}) )}
foreach ($p in $ExcludeProperty) { $propList = $propList.where({$_ -notlike $p}) } foreach ($p in $ExcludeProperty) { $propList = $propList.where({$_ -notlike $p}) }
if (($propList -notcontains $Key) -and if (($propList -notcontains $Key) -and
@@ -199,19 +212,29 @@
else {$Rowhash[$row.$key] = $rowNo } else {$Rowhash[$row.$key] = $rowNo }
$rowNo ++ $rowNo ++
} }
if ($DifferenceObject.count -gt $Rowhash.Keys.Count) {
Write-Warning -Message "Difference object has $($DifferenceObject.Count) rows; but only $($Rowhash.keys.count) unique keys"
}
if ($Key -eq '*') {$key = "_ALL"} if ($Key -eq '*') {$key = "_ALL"}
#endregion #endregion
#We need to know all the properties we've met on the objects we've diffed
$eDiffProps = [ordered]@{}
#When we do a compare object changes will result in two rows so we group them and join them together.
$expandedDiff = Compare-Object -ReferenceObject $ReferenceObject -DifferenceObject $DifferenceObject -Property $propList -PassThru -IncludeEqual | $expandedDiff = Compare-Object -ReferenceObject $ReferenceObject -DifferenceObject $DifferenceObject -Property $propList -PassThru -IncludeEqual |
Group-Object -Property $key | ForEach-Object { Group-Object -Property $key | ForEach-Object {
#The value of the key column is the name of the group. #The value of the key column is the name of the Group.
$keyval = $_.name $keyval = $_.name
#we're going to create a custom object from a hash table. ??Might no longer need to preserve the field order #we're going to create a custom object from a hash table.
$hash = [ordered]@{} $hash = [ordered]@{}
foreach ($result in $_.Group) { foreach ($result in $_.Group) {
if ($result.SideIndicator -ne "=>") {$hash["_Row"] = $result._Row } if ($result.SideIndicator -ne "=>") {$hash["_Row"] = $result._Row }
elseif (-not $hash["$DiffPrefix Row"]) {$hash["_Row"] = "" } elseif (-not $hash["$DiffPrefix Row"]) {$hash["_Row"] = "" }
#if we have already set the side, be this must the second record, so set side to indicate "changed" #if we have already set the side, this must be the second record, so set side to indicate "changed"; if we got two "Same" indicators we may have a classh of keys
if ($hash.Side) {$hash.Side = "<>"} else {$hash["Side"] = $result.SideIndicator} if ($hash.Side) {
if ($hash.Side -eq $result.SideIndicator) {Write-Warning -Message "'$keyval' may be a duplicate."}
$hash.Side = "<>"
}
else {$hash["Side"] = $result.SideIndicator}
switch ($hash.side) { switch ($hash.side) {
'==' { $hash["$DiffPrefix is"] = 'Same' } '==' { $hash["$DiffPrefix is"] = 'Same' }
'=>' { $hash["$DiffPrefix is"] = 'Added' } '=>' { $hash["$DiffPrefix is"] = 'Added' }
@@ -224,7 +247,7 @@
} }
'<=' { $hash["$DiffPrefix is"] = 'Removed'} '<=' { $hash["$DiffPrefix is"] = 'Removed'}
} }
#find the number of the row in the the "difference" object which has this key. If it is the object is only the reference this will be blank. #find the number of the row in the the "difference" object which has this key. If it is the object is only in the reference this will be blank.
$hash["$DiffPrefix Row"] = $Rowhash[$keyval] $hash["$DiffPrefix Row"] = $Rowhash[$keyval]
$hash[$key] = $keyval $hash[$key] = $keyval
#Create FieldName and/or =>FieldName columns #Create FieldName and/or =>FieldName columns
@@ -236,6 +259,8 @@
elseif ($result.SideIndicator -eq "=>") { $hash[("$DiffPrefix $p")] = $result.$P} elseif ($result.SideIndicator -eq "=>") { $hash[("$DiffPrefix $p")] = $result.$P}
} }
} }
foreach ($k in $hash.keys) {$eDiffProps[$k] = $true}
[Pscustomobject]$hash [Pscustomobject]$hash
} | Sort-Object -Property "_row" } | Sort-Object -Property "_row"
@@ -246,35 +271,35 @@
$expandedDiff = $expandedDiff | Sort-Object -Property "$DiffPrefix Row" $expandedDiff = $expandedDiff | Sort-Object -Property "$DiffPrefix Row"
for ($i = 1; $i -lt $expandedDiff.Count; $i++) {if (-not $expandedDiff[$i]."_Row") {$expandedDiff[$i]."_Row" = $expandedDiff[$i-1]."_Row" } } for ($i = 1; $i -lt $expandedDiff.Count; $i++) {if (-not $expandedDiff[$i]."_Row") {$expandedDiff[$i]."_Row" = $expandedDiff[$i-1]."_Row" } }
$AllProps = @("_Row") + $OutputProps + $expandedDiff[0].psobject.properties.name.where({$_ -notin ($outputProps + @("_row","side","SideIndicator","_ALL" ))}) $AllProps = @("_Row") + $OutputProps + $eDiffProps.keys.where({$_ -notin ($outputProps + @("_row","side","SideIndicator","_ALL" ))})
if ($PassThru -or -not $OutputFile) {return ($expandedDiff | Select-Object -Property $allprops | Sort-Object -Property "_row", "$DiffPrefix Row" | Update-FirstObjectProperties ) } if ($PassThru -or -not $OutputFile) {return ($expandedDiff | Select-Object -Property $allprops | Sort-Object -Property "_row", "$DiffPrefix Row" ) }
elseif ($PSCmdlet.ShouldProcess($OutputFile,"Write Output to Excel file")) { elseif ($PSCmdlet.ShouldProcess($OutputFile,"Write Output to Excel file")) {
$expandedDiff = $expandedDiff | Sort-Object -Property "_row", "$DiffPrefix Row" $expandedDiff = $expandedDiff | Sort-Object -Property "_row", "$DiffPrefix Row"
$xl = $expandedDiff | Select-Object -Property $OutputProps | Update-FirstObjectProperties | $xl = $expandedDiff | Select-Object -Property $OutputProps | Update-FirstObjectProperties |
Export-Excel -Path $OutputFile -WorkSheetname $OutputSheetName -FreezeTopRow -BoldTopRow -AutoSize -AutoFilter -PassThru Export-Excel -Path $OutputFile -Worksheetname $OutputSheetName -FreezeTopRow -BoldTopRow -AutoSize -AutoFilter -PassThru
$ws = $xl.Workbook.Worksheets[$OutputSheetName] $ws = $xl.Workbook.Worksheets[$OutputSheetName]
for ($i = 0; $i -lt $expandedDiff.Count; $i++ ) { for ($i = 0; $i -lt $expandedDiff.Count; $i++ ) {
if ( $expandedDiff[$i].side -ne "==" ) { if ( $expandedDiff[$i].side -ne "==" ) {
Set-ExcelRange -WorkSheet $ws -Range ("A" + ($i + 2 )) -FontColor $KeyFontColor Set-ExcelRange -Worksheet $ws -Range ("A" + ($i + 2 )) -FontColor $KeyFontColor
} }
elseif ( $HideEqual ) {$ws.row($i+2).hidden = $true } elseif ( $HideEqual ) {$ws.row($i+2).hidden = $true }
if ( $expandedDiff[$i].side -eq "<>" ) { if ( $expandedDiff[$i].side -eq "<>" ) {
$range = $ws.Dimension -replace "\d+", ($i + 2 ) $range = $ws.Dimension -replace "\d+", ($i + 2 )
Set-ExcelRange -WorkSheet $ws -Range $range -BackgroundColor $ChangeBackgroundColor Set-ExcelRange -Worksheet $ws -Range $range -BackgroundColor $ChangeBackgroundColor
} }
elseif ( $expandedDiff[$i].side -eq "<=" ) { elseif ( $expandedDiff[$i].side -eq "<=" ) {
$rangeR1C1 = "R[{0}]C[1]:R[{0}]C[{1}]" -f ($i + 2 ) , $lastRefColNo $rangeR1C1 = "R[{0}]C[1]:R[{0}]C[{1}]" -f ($i + 2 ) , $lastRefColNo
$range = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1($rangeR1C1,0,0) $range = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1($rangeR1C1,0,0)
Set-ExcelRange -WorkSheet $ws -Range $range -BackgroundColor $DeleteBackgroundColor Set-ExcelRange -Worksheet $ws -Range $range -BackgroundColor $DeleteBackgroundColor
} }
elseif ( $expandedDiff[$i].side -eq "=>" ) { elseif ( $expandedDiff[$i].side -eq "=>" ) {
if ($propList.count -gt 1) { if ($propList.count -gt 1) {
$rangeR1C1 = "R[{0}]C[{1}]:R[{0}]C[{2}]" -f ($i + 2 ) , $FirstDiffColNo , $lastDiffColNo $rangeR1C1 = "R[{0}]C[{1}]:R[{0}]C[{2}]" -f ($i + 2 ) , $FirstDiffColNo , $lastDiffColNo
$range = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1($rangeR1C1,0,0) $range = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1($rangeR1C1,0,0)
Set-ExcelRange -WorkSheet $ws -Range $range -BackgroundColor $AddBackgroundColor Set-ExcelRange -Worksheet $ws -Range $range -BackgroundColor $AddBackgroundColor
} }
Set-ExcelRange -WorkSheet $ws -Range ("A" + ($i + 2 )) -BackgroundColor $AddBackgroundColor Set-ExcelRange -Worksheet $ws -Range ("A" + ($i + 2 )) -BackgroundColor $AddBackgroundColor
} }
} }
Close-ExcelPackage -ExcelPackage $xl -Show:$Show Close-ExcelPackage -ExcelPackage $xl -Show:$Show
@@ -284,9 +309,9 @@
Function Merge-MultipleSheets { Function Merge-MultipleSheets {
<# <#
.Synopsis .Synopsis
Merges worksheets into a single worksheet with differences marked up. Merges Worksheets into a single Worksheet with differences marked up.
.Description .Description
The Merge worksheet command combines 2 sheets. Merge-MultipleSheets is designed to merge more than 2. The Merge Worksheet command combines 2 sheets. Merge-MultipleSheets is designed to merge more than 2.
So if asked to merge sheets A,B,C which contain Services, with a Name, Displayname and Start mode, where "name" is treated as the key So if asked to merge sheets A,B,C which contain Services, with a Name, Displayname and Start mode, where "name" is treated as the key
Merge-MultipleSheets calls Merge-Worksheet to merge Name, Displayname and Start mode, from sheets A and C Merge-MultipleSheets calls Merge-Worksheet to merge Name, Displayname and Start mode, from sheets A and C
the result has column headings -Row, Name, DisplayName, Startmode, C-DisplayName, C-StartMode C-Is, C-Row the result has column headings -Row, Name, DisplayName, Startmode, C-DisplayName, C-StartMode C-Is, C-Row
@@ -306,22 +331,22 @@ Function Merge-MultipleSheets {
However if Sheet B is the reference sheet, A and C will be seen to have an item removed; However if Sheet B is the reference sheet, A and C will be seen to have an item removed;
and if B is processed before C, the extra item is known when C is processed and so C is considered to be missing that item. and if B is processed before C, the extra item is known when C is processed and so C is considered to be missing that item.
.Example .Example
dir Server*.xlsx | Merge-MulipleSheets -WorkSheetName Services -OutputFile Test2.xlsx -OutputSheetName Services -Show dir Server*.xlsx | Merge-MulipleSheets -WorksheetName Services -OutputFile Test2.xlsx -OutputSheetName Services -Show
We are auditing servers and each one has a workbook in the current directory which contains a "Services" worksheet (the result of We are auditing servers and each one has a workbook in the current directory which contains a "Services" Worksheet (the result of
Get-WmiObject -Class win32_service | Select-Object -Property Name, Displayname, Startmode Get-WmiObject -Class win32_service | Select-Object -Property Name, Displayname, Startmode
No key is specified so the key is assumed to be the "Name" column. The files are merged and the result is opened on completion. No key is specified so the key is assumed to be the "Name" column. The files are merged and the result is opened on completion.
.Example .Example
dir Serv*.xlsx | Merge-MulipleSheets -WorkSheetName Software -Key "*" -ExcludeProperty Install* -OutputFile Test2.xlsx -OutputSheetName Software -Show dir Serv*.xlsx | Merge-MulipleSheets -WorksheetName Software -Key "*" -ExcludeProperty Install* -OutputFile Test2.xlsx -OutputSheetName Software -Show
The server audit files in the previous example also have "Software" worksheet, but no single field on that sheet works as a key. The server audit files in the previous example also have "Software" Worksheet, but no single field on that sheet works as a key.
Specifying "*" for the key produces a compound key using all non-excluded fields (and the installation date and file location are excluded). Specifying "*" for the key produces a compound key using all non-excluded fields (and the installation date and file location are excluded).
.Example .Example
Merge-MulipleSheets -Path hotfixes.xlsx -WorkSheetName Serv* -Key hotfixid -OutputFile test2.xlsx -OutputSheetName hotfixes -HideRowNumbers -Show Merge-MulipleSheets -Path hotfixes.xlsx -WorksheetName Serv* -Key hotfixid -OutputFile test2.xlsx -OutputSheetName hotfixes -HideRowNumbers -Show
This time all the servers have written their hofix information to their own worksheets in a shared Excel workbook named "Hotfixes" This time all the servers have written their hofix information to their own Worksheets in a shared Excel workbook named "Hotfixes"
(the information was obtained by running Get-Hotfix | Sort-Object -Property description,hotfixid | Select-Object -Property Description,HotfixID) (the information was obtained by running Get-Hotfix | Sort-Object -Property description,hotfixid | Select-Object -Property Description,HotfixID)
This ignores any sheets which are not named "Serv*", and uses the HotfixID as the key ; in this version the row numbers are hidden. This ignores any sheets which are not named "Serv*", and uses the HotfixID as the key ; in this version the row numbers are hidden.
#> #>
[cmdletbinding()] [cmdletbinding()]
[Alias("Merge-MulipleSheets")] #[Alias("Merge-MulipleSheets")] #There was a spelling error in the first release. This was there to ensure things didn't break but intelisense gave the alias first.
param ( param (
#Paths to the files to be merged. #Paths to the files to be merged.
[Parameter(Mandatory=$true,ValueFromPipeline=$true)] [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
@@ -335,12 +360,12 @@ Function Merge-MultipleSheets {
#Automatically generate property names (P1, P2, P3, ..) instead of the using the values the top row of the sheet. #Automatically generate property names (P1, P2, P3, ..) instead of the using the values the top row of the sheet.
[switch]$NoHeader, [switch]$NoHeader,
#Name(s) of worksheets to compare, #Name(s) of Worksheets to compare,
$WorkSheetName = "Sheet1", $WorksheetName = "Sheet1",
#File to write output to #File to write output to
[Alias('OutFile')] [Alias('OutFile')]
$OutputFile = ".\temp.xlsx", $OutputFile = ".\temp.xlsx",
#Name of worksheet to output - if none specified will use the reference worksheet name. #Name of Worksheet to output - if none specified will use the reference Worksheet name.
[Alias('OutSheet')] [Alias('OutSheet')]
$OutputSheetName = "Sheet1", $OutputSheetName = "Sheet1",
#Properties to include in the DIFF - supports wildcards, default is "*". #Properties to include in the DIFF - supports wildcards, default is "*".
@@ -367,50 +392,51 @@ Function Merge-MultipleSheets {
begin { $filestoProcess = @() } begin { $filestoProcess = @() }
process { $filestoProcess += $Path} process { $filestoProcess += $Path}
end { end {
if ($filestoProcess.Count -eq 1 -and $WorkSheetName -match '\*') { if ($filestoProcess.Count -eq 1 -and $WorksheetName -match '\*') {
Write-Progress -Activity "Merging sheets" -CurrentOperation "Expanding * to names of sheets in $($filestoProcess[0]). " Write-Progress -Activity "Merging sheets" -CurrentOperation "Expanding * to names of sheets in $($filestoProcess[0]). "
$excel = Open-ExcelPackage -Path $filestoProcess $excel = Open-ExcelPackage -Path $filestoProcess
$WorksheetName = $excel.Workbook.Worksheets.Name.where({$_ -like $WorkSheetName}) $WorksheetName = $excel.Workbook.Worksheets.Name.where({$_ -like $WorksheetName})
Close-ExcelPackage -NoSave -ExcelPackage $excel Close-ExcelPackage -NoSave -ExcelPackage $excel
} }
#Merge indentically named sheets in different work books; #Merge identically named sheets in different work books;
if ($filestoProcess.Count -ge 2 -and $WorkSheetName -is "string" ) { if ($filestoProcess.Count -ge 2 -and $WorksheetName -is "string" ) {
Get-Variable -Name 'HeaderName','NoHeader','StartRow','Key','Property','ExcludeProperty','WorkSheetName' -ErrorAction SilentlyContinue | Get-Variable -Name 'HeaderName','NoHeader','StartRow','Key','Property','ExcludeProperty','WorksheetName' -ErrorAction SilentlyContinue |
Where-Object {$_.Value} | ForEach-Object -Begin {$params= @{} } -Process {$params[$_.Name] = $_.Value} Where-Object {$_.Value} | ForEach-Object -Begin {$params= @{} } -Process {$params[$_.Name] = $_.Value}
Write-Progress -Activity "Merging sheets" -CurrentOperation "Comparing $($filestoProcess[-1]) against $($filestoProcess[0]). " Write-Progress -Activity "Merging sheets" -CurrentOperation "comparing '$WorksheetName' in $($filestoProcess[-1]) against $($filestoProcess[0]). "
$merged = Merge-Worksheet @params -Referencefile $filestoProcess[0] -Differencefile $filestoProcess[-1] $merged = Merge-Worksheet @params -Referencefile $filestoProcess[0] -Differencefile $filestoProcess[-1]
$nextFileNo = 2 $nextFileNo = 2
while ($nextFileNo -lt $filestoProcess.count -and $merged) { while ($nextFileNo -lt $filestoProcess.count -and $merged) {
Write-Progress -Activity "Merging sheets" -CurrentOperation "Comparing $($filestoProcess[-$nextFileNo]) against $($filestoProcess[0]). " Write-Progress -Activity "Merging sheets" -CurrentOperation "comparing '$WorksheetName' in $($filestoProcess[-$nextFileNo]) against $($filestoProcess[0]). "
$merged = Merge-Worksheet @params -ReferenceObject $merged -Differencefile $filestoProcess[-$nextFileNo] $merged = Merge-Worksheet @params -ReferenceObject $merged -Differencefile $filestoProcess[-$nextFileNo]
$nextFileNo ++ $nextFileNo ++
} }
} }
#Merge different sheets from one workbook #Merge different sheets from one workbook
elseif ($filestoProcess.Count -eq 1 -and $WorkSheetName.Count -ge 2 ) { elseif ($filestoProcess.Count -eq 1 -and $WorksheetName.Count -ge 2 ) {
Get-Variable -Name 'HeaderName','NoHeader','StartRow','Key','Property','ExcludeProperty' -ErrorAction SilentlyContinue | Get-Variable -Name 'HeaderName','NoHeader','StartRow','Key','Property','ExcludeProperty' -ErrorAction SilentlyContinue |
Where-Object {$_.Value} | ForEach-Object -Begin {$params= @{} } -Process {$params[$_.Name] = $_.Value} Where-Object {$_.Value} | ForEach-Object -Begin {$params= @{} } -Process {$params[$_.Name] = $_.Value}
Write-Progress -Activity "Merging sheets" -CurrentOperation "Comparing $($WorkSheetName[-1]) against $($WorkSheetName[0]). " Write-Progress -Activity "Merging sheets" -CurrentOperation "Comparing $($WorksheetName[-1]) against $($WorksheetName[0]). "
$merged = Merge-Worksheet @params -Referencefile $filestoProcess[0] -Differencefile $filestoProcess[0] -WorkSheetName $WorkSheetName[0,-1] $merged = Merge-Worksheet @params -Referencefile $filestoProcess[0] -Differencefile $filestoProcess[0] -WorksheetName $WorksheetName[0,-1]
$nextSheetNo = 2 $nextSheetNo = 2
while ($nextSheetNo -lt $WorkSheetName.count -and $merged) { while ($nextSheetNo -lt $WorksheetName.count -and $merged) {
Write-Progress -Activity "Merging sheets" -CurrentOperation "Comparing $($WorkSheetName[-$nextSheetNo]) against $($WorkSheetName[0]). " Write-Progress -Activity "Merging sheets" -CurrentOperation "Comparing $($WorksheetName[-$nextSheetNo]) against $($WorksheetName[0]). "
$merged = Merge-Worksheet @params -ReferenceObject $merged -Differencefile $filestoProcess[0] -WorkSheetName $WorkSheetName[-$nextSheetNo] -DiffPrefix $WorkSheetName[-$nextSheetNo] $merged = Merge-Worksheet @params -ReferenceObject $merged -Differencefile $filestoProcess[0] -WorksheetName $WorksheetName[-$nextSheetNo] -DiffPrefix $WorksheetName[-$nextSheetNo]
$nextSheetNo ++ $nextSheetNo ++
} }
} }
#We either need one worksheet name and many files or one file and many sheets. #We either need one Worksheet name and many files or one file and many sheets.
else { Write-Warning -Message "Need at least two files to process" ; return } else { Write-Warning -Message "Need at least two files to process" ; return }
#if the process didn't return data then abandon now. #if the process didn't return data then abandon now.
if (-not $merged) {Write-Warning -Message "The merge operation did not return any data."; return } if (-not $merged) {Write-Warning -Message "The merge operation did not return any data."; return }
$orderByProperties = $merged[0].psobject.properties.where({$_.name -match "row$"}).name $orderByProperties = $merged[0].psobject.properties.where({$_.name -match "row$"}).name
Write-Progress -Activity "Merging sheets" -CurrentOperation "Creating output sheet '$OutputSheetName' in $OutputFile" Write-Progress -Activity "Merging sheets" -CurrentOperation "creating output sheet '$OutputSheetName' in $OutputFile"
$excel = $merged | Sort-Object -Property $orderByProperties | Update-FirstObjectProperties | $excel = $merged | Sort-Object -Property $orderByProperties |
Export-Excel -Path $OutputFile -WorkSheetname $OutputSheetName -ClearSheet -BoldTopRow -AutoFilter -PassThru Export-Excel -Path $OutputFile -Worksheetname $OutputSheetName -ClearSheet -BoldTopRow -AutoFilter -PassThru
$sheet = $excel.Workbook.Worksheets[$OutputSheetName] $sheet = $excel.Workbook.Worksheets[$OutputSheetName]
#We will put in a conditional format for "if all the others are not flagged as 'same'" to mark rows where something is added, removed or changed #We will put in a conditional format for "if all the others are not flagged as 'same'" to mark rows where something is added, removed or changed
@@ -424,8 +450,8 @@ Function Merge-MultipleSheets {
if ($filesToProcess.Count -ge 2) { if ($filesToProcess.Count -ge 2) {
$refPrefix = (Split-Path -Path $filestoProcess[0] -Leaf) -replace "\.xlsx$"," " $refPrefix = (Split-Path -Path $filestoProcess[0] -Leaf) -replace "\.xlsx$"," "
} }
else {$refPrefix = $WorkSheetName[0] } else {$refPrefix = $WorksheetName[0] }
Write-Progress -Activity "Merging sheets" -CurrentOperation "Applying formatting to sheet '$OutputSheetName' in $OutputFile" Write-Progress -Activity "Merging sheets" -CurrentOperation "applying formatting to sheet '$OutputSheetName' in $OutputFile"
#Find the column headings which are in the form "diffFile is"; which will hold 'Same', 'Added' or 'Changed' #Find the column headings which are in the form "diffFile is"; which will hold 'Same', 'Added' or 'Changed'
foreach ($cell in $sheet.Cells[($sheet.Dimension.Address -replace "\d+$","1")].Where({$_.value -match "\sIS$"}) ) { foreach ($cell in $sheet.Cells[($sheet.Dimension.Address -replace "\d+$","1")].Where({$_.value -match "\sIS$"}) ) {
#Work leftwards across the headings applying conditional formatting which says #Work leftwards across the headings applying conditional formatting which says
@@ -434,7 +460,7 @@ Function Merge-MultipleSheets {
$columnNo = $cell.start.Column -1 $columnNo = $cell.start.Column -1
$cellAddr = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R1C$columnNo",1,$columnNo) $cellAddr = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R1C$columnNo",1,$columnNo)
while ($sheet.cells[$cellAddr].value -match $prefix) { while ($sheet.cells[$cellAddr].value -match $prefix) {
$condFormattingParams = @{RuleType='Expression'; BackgroundPattern='Solid'; WorkSheet=$sheet; Range=$([OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R[1]C[$columnNo]:R[1048576]C[$columnNo]",0,0)) } $condFormattingParams = @{RuleType='Expression'; BackgroundPattern='Solid'; Worksheet=$sheet; StopIfTrue=$true; Range=$([OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R[1]C[$columnNo]:R[1048576]C[$columnNo]",0,0)) }
Add-ConditionalFormatting @condFormattingParams -ConditionValue ($cell.Address + '="Added"' ) -BackgroundColor $AddBackgroundColor Add-ConditionalFormatting @condFormattingParams -ConditionValue ($cell.Address + '="Added"' ) -BackgroundColor $AddBackgroundColor
Add-ConditionalFormatting @condFormattingParams -ConditionValue ($cell.Address + '="Changed"') -BackgroundColor $ChangeBackgroundColor Add-ConditionalFormatting @condFormattingParams -ConditionValue ($cell.Address + '="Changed"') -BackgroundColor $ChangeBackgroundColor
Add-ConditionalFormatting @condFormattingParams -ConditionValue ($cell.Address + '="Removed"') -BackgroundColor $DeleteBackgroundColor Add-ConditionalFormatting @condFormattingParams -ConditionValue ($cell.Address + '="Removed"') -BackgroundColor $DeleteBackgroundColor
@@ -450,15 +476,16 @@ Function Merge-MultipleSheets {
$nameRegex = $colNames -Join '|' $nameRegex = $colNames -Join '|'
foreach ($cell in $sheet.Cells[($sheet.Dimension.Address -replace "\d+$","1")].Where({$_.value -Notmatch $nameRegex}) ) { foreach ($cell in $sheet.Cells[($sheet.Dimension.Address -replace "\d+$","1")].Where({$_.value -Notmatch $nameRegex}) ) {
$cell.Value = $refPrefix + $cell.Value $cell.Value = $refPrefix + $cell.Value
$condFormattingParams = @{RuleType='Expression'; BackgroundPattern='None'; WorkSheet=$sheet; Range=[OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R[2]C[$($cell.start.column)]:R[1048576]C[$($cell.start.column)]",0,0)} $condFormattingParams = @{RuleType='Expression'; BackgroundPattern='Solid'; Worksheet=$sheet; StopIfTrue=$true; Range=[OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R[2]C[$($cell.start.column)]:R[1048576]C[$($cell.start.column)]",0,0)}
Add-ConditionalFormatting @condFormattingParams -ConditionValue ("OR(" +(($sameChecks -join ",") -replace '<>"Same"','="Added"' ) +")" ) -BackgroundColor $DeleteBackgroundColor Add-ConditionalFormatting @condFormattingParams -ConditionValue ("OR(" +(($sameChecks -join ",") -replace '<>"Same"','="Added"' ) +")" ) -BackgroundColor $DeleteBackgroundColor
Add-ConditionalFormatting @condFormattingParams -ConditionValue ("AND(" +(($sameChecks -join ",") -replace '<>"Same"','="Changed"') +")" ) -BackgroundColor $ChangeBackgroundColor
} }
#We've made a bunch of things wider so now is the time to autofit columns. Any hiding has to come AFTER this, because it unhides things #We've made a bunch of things wider so now is the time to autofit columns. Any hiding has to come AFTER this, because it unhides things
$sheet.Cells.AutoFitColumns() $sheet.Cells.AutoFitColumns()
#if we have a key field (we didn't concatenate all fields) use what we built up in $sameChecks to apply conditional formatting to it (Row no will be in column A, Key in Column B) #if we have a key field (we didn't concatenate all fields) use what we built up in $sameChecks to apply conditional formatting to it (Row no will be in column A, Key in Column B)
if ($Key -ne '*') { if ($Key -ne '*') {
Add-ConditionalFormatting -WorkSheet $sheet -Range "B2:B1048576" -ForeGroundColor $KeyFontColor -BackgroundPattern 'None' -RuleType Expression -ConditionValue ("OR(" +($sameChecks -join ",") +")" ) Add-ConditionalFormatting -Worksheet $sheet -Range "B2:B1048576" -ForeGroundColor $KeyFontColor -BackgroundPattern 'None' -RuleType Expression -ConditionValue ("OR(" +($sameChecks -join ",") +")" )
$sheet.view.FreezePanes(2, 3) $sheet.view.FreezePanes(2, 3)
} }
else {$sheet.view.FreezePanes(2, 2) } else {$sheet.view.FreezePanes(2, 2) }

View File

@@ -163,7 +163,7 @@
#region Apply formatting #region Apply formatting
$params = @{} $params = @{}
foreach ($p in @('Underline','Bold','Italic','StrikeThru','FontSize','FontShift','NumberFormat','TextRotation', foreach ($p in @('Underline','Bold','Italic','StrikeThru', 'FontName', 'FontSize','FontShift','NumberFormat','TextRotation',
'WrapText', 'HorizontalAlignment','VerticalAlignment', 'Autosize', 'Width', 'FontColor' 'WrapText', 'HorizontalAlignment','VerticalAlignment', 'Autosize', 'Width', 'FontColor'
'BorderAround', 'BackgroundColor', 'BackgroundPattern', 'PatternColor')) { 'BorderAround', 'BackgroundColor', 'BackgroundPattern', 'PatternColor')) {
if ($PSBoundParameters.ContainsKey($p)) {$params[$p] = $PSBoundParameters[$p]} if ($PSBoundParameters.ContainsKey($p)) {$params[$p] = $PSBoundParameters[$p]}

View File

@@ -156,7 +156,7 @@
}} }}
#region Apply formatting #region Apply formatting
$params = @{} $params = @{}
foreach ($p in @('Underline','Bold','Italic','StrikeThru','FontSize', 'FontShift','NumberFormat','TextRotation', foreach ($p in @('Underline','Bold','Italic','StrikeThru', 'FontName', 'FontSize', 'FontShift','NumberFormat','TextRotation',
'WrapText', 'HorizontalAlignment','VerticalAlignment', 'Height', 'FontColor' 'WrapText', 'HorizontalAlignment','VerticalAlignment', 'Height', 'FontColor'
'BorderAround', 'BorderBottom', 'BorderTop', 'BorderLeft', 'BorderRight', 'BorderColor', 'BorderAround', 'BorderBottom', 'BorderTop', 'BorderLeft', 'BorderRight', 'BorderColor',
'BackgroundColor', 'BackgroundPattern', 'PatternColor')) { 'BackgroundColor', 'BackgroundPattern', 'PatternColor')) {

View File

@@ -136,6 +136,9 @@
if ($PSBoundParameters.ContainsKey('FontSize')){ if ($PSBoundParameters.ContainsKey('FontSize')){
$Range.Style.Font.Size = $FontSize $Range.Style.Font.Size = $FontSize
} }
if ($PSBoundParameters.ContainsKey('FontName')){
$Range.Style.Font.Name = $FontName
}
if ($PSBoundParameters.ContainsKey('FontShift')){ if ($PSBoundParameters.ContainsKey('FontShift')){
$Range.Style.Font.VerticalAlign = $FontShift $Range.Style.Font.VerticalAlign = $FontShift
} }

View File

@@ -321,19 +321,21 @@ Describe "Merge Multiple sheets" {
} }
it "Creared Conditional formatting rules " { it "Creared Conditional formatting rules " {
$cf=$ws.ConditionalFormatting $cf=$ws.ConditionalFormatting
$cf.Count | Should be 15 $cf.Count | Should be 17
$cf[14].Address.Address | Should be 'B2:B1048576' $cf[16].Address.Address | Should be 'B2:B1048576'
$cf[16].Type | Should be 'Expression'
$cf[16].Formula | Should be 'OR(G2<>"Same",K2<>"Same")'
$cf[16].Style.Font.Color.Color.Name | Should be "FFFF0000"
$cf[14].Address.Address | Should be 'D2:D1048576'
$cf[14].Type | Should be 'Expression' $cf[14].Type | Should be 'Expression'
$cf[14].Formula | Should be 'OR(G2<>"Same",K2<>"Same")' $cf[14].Formula | Should be 'OR(G2="Added",K2="Added")'
$cf[14].Style.Font.Color.Color.Name | Should be "FFFF0000" $cf[14].Style.Fill.BackgroundColor.Color.Name | Should be 'ffffb6c1'
$cf[13].Address.Address | Should be 'D2:D1048576' $cf[14].Style.Fill.PatternType.ToString() | Should be 'Solid'
$cf[13].Type | Should be 'Expression'
$cf[13].Formula | Should be 'OR(G2="Added",K2="Added")'
$cf[13].Style.Fill.BackgroundColor.Color.Name | Should be 'ffffb6c1'
$cf[ 0].Address.Address | Should be 'F1:F1048576' $cf[ 0].Address.Address | Should be 'F1:F1048576'
$cf[ 0].Type | Should be 'Expression' $cf[ 0].Type | Should be 'Expression'
$cf[ 0].Formula | Should be 'G1="Added"' $cf[ 0].Formula | Should be 'G1="Added"'
$cf[ 0].Style.Fill.BackgroundColor.Color.Name | Should be 'ffffa500' $cf[ 0].Style.Fill.BackgroundColor.Color.Name | Should be 'ffffa500'
$cf[ 0].Style.Fill.PatternType.ToString() | Should be 'Solid'
} }
} }
} }

View File

@@ -1,26 +1,28 @@
#Requires -Modules Pester #Requires -Modules Pester
remove-module importExcel -erroraction silentlyContinue
Import-Module $PSScriptRoot\..\ImportExcel.psd1 -Force Import-Module $PSScriptRoot\..\ImportExcel.psd1 -Force
Describe "Check if Function aliases exist" { Describe "Check if Function aliases exist" {
It "Set-Column should exist" { It "Set-Column should exist" {
Get-Command Set-Column | Should Not Be $null ${Alias:Set-Column} | Should Not BeNullOrEmpty
} }
It "Set-Row should exist" { It "Set-Row should exist" {
Get-Command Set-Row | Should Not Be $null ${Alias:Set-Row} | Should Not BeNullOrEmpty
} }
It "Set-Format should exist" { It "Set-Format should exist" {
Get-Command Set-Format | Should Not Be $null ${Alias:Set-Format} | Should Not BeNullOrEmpty
} }
It "Merge-MulipleSheets should exist" { <#It "Merge-MulipleSheets should exist" {
Get-Command Merge-MulipleSheets | Should Not Be $null Get-Command Merge-MulipleSheets | Should Not Be $null
} }
#>
It "New-ExcelChart should exist" { It "New-ExcelChart should exist" {
Get-Command New-ExcelChart | Should Not Be $null ${Alias:New-ExcelChart} | Should Not BeNullOrEmpty
} }
} }

View File

@@ -137,11 +137,11 @@ Describe "Set-ExcelColumn, Set-ExcelRow and Set-ExcelRange" {
$c = Set-ExcelColumn -PassThru -Worksheet $ws -Heading "Total" -Value "=Quantity*Price" -NumberFormat "£#,###.00" -FontColor Blue -Bold -HorizontalAlignment Right -VerticalAlignment Top $c = Set-ExcelColumn -PassThru -Worksheet $ws -Heading "Total" -Value "=Quantity*Price" -NumberFormat "£#,###.00" -FontColor Blue -Bold -HorizontalAlignment Right -VerticalAlignment Top
$r = Set-ExcelRow -PassThru -Worksheet $ws -StartColumn 3 -BorderAround Thin -Italic -Underline -FontSize 14 -Value {"=sum($columnName`2:$columnName$endrow)" } -VerticalAlignment Bottom $r = Set-ExcelRow -PassThru -Worksheet $ws -StartColumn 3 -BorderAround Thin -Italic -Underline -FontSize 14 -Value {"=sum($columnName`2:$columnName$endrow)" } -VerticalAlignment Bottom
Set-ExcelRange -Address $excel.Workbook.Worksheets["Sheet1"].cells["b3"] -HorizontalAlignment Right -VerticalAlignment Center -BorderAround Thick -BorderColor Red -StrikeThru Set-ExcelRange -Address $excel.Workbook.Worksheets["Sheet1"].Cells["b3"] -HorizontalAlignment Right -VerticalAlignment Center -BorderAround Thick -BorderColor Red -StrikeThru
Set-ExcelRange -Address $excel.Workbook.Worksheets["Sheet1"].cells["c3"] -BorderColor Red -BorderTop DashDot -BorderLeft DashDotDot -BorderBottom Dashed -BorderRight Dotted Set-ExcelRange -Address $excel.Workbook.Worksheets["Sheet1"].Cells["c3"] -BorderColor Red -BorderTop DashDot -BorderLeft DashDotDot -BorderBottom Dashed -BorderRight Dotted
Set-ExcelRange -WorkSheet $ws -Range "E3" -Bold:$false -FontShift Superscript -HorizontalAlignment Left Set-ExcelRange -WorkSheet $ws -Range "E3" -Bold:$false -FontShift Superscript -HorizontalAlignment Left
Set-ExcelRange -WorkSheet $ws -Range "E1" -ResetFont -HorizontalAlignment General Set-ExcelRange -WorkSheet $ws -Range "E1" -ResetFont -HorizontalAlignment General -FontName "Courier New" -fontSize 9
Set-ExcelRange -Address $ws.cells["E7"] -ResetFont -WrapText -BackgroundColor AliceBlue -BackgroundPattern DarkTrellis -PatternColor Red -NumberFormat "£#,###.00" Set-ExcelRange -Address $ws.Cells["E7"] -ResetFont -WrapText -BackgroundColor AliceBlue -BackgroundPattern DarkTrellis -PatternColor Red -NumberFormat "£#,###.00"
Set-ExcelRange -Address $ws.Column(1) -Width 0 Set-ExcelRange -Address $ws.Column(1) -Width 0
Set-ExcelRange -Address $ws.Column(2) -AutoFit Set-ExcelRange -Address $ws.Column(2) -AutoFit
Set-ExcelRange -Address $ws.Cells["E:E"] -AutoFit Set-ExcelRange -Address $ws.Cells["E:E"] -AutoFit
@@ -167,50 +167,52 @@ Describe "Set-ExcelColumn, Set-ExcelRow and Set-ExcelRange" {
$ws.Row(5).height | Should be 0 $ws.Row(5).height | Should be 0
} }
it "Set a column formula, with numberformat, color, bold face and alignment " { it "Set a column formula, with numberformat, color, bold face and alignment " {
$ws.cells["e2"].Formula | Should be "Quantity*Price" $ws.Cells["e2"].Formula | Should be "Quantity*Price"
$ws.cells["e2"].Value | Should be 147.63 $ws.Cells["e2"].Value | Should be 147.63
$ws.cells["e2"].Style.Font.Color.rgb | Should be "FF0000FF" $ws.Cells["e2"].Style.Font.Color.rgb | Should be "FF0000FF"
$ws.cells["e2"].Style.Font.Bold | Should be $true $ws.Cells["e2"].Style.Font.Bold | Should be $true
$ws.cells["e2"].Style.Font.VerticalAlign | Should be "None" $ws.Cells["e2"].Style.Font.VerticalAlign | Should be "None"
$ws.cells["e2"].Style.Numberformat.format | Should be "£#,###.00" $ws.Cells["e2"].Style.Numberformat.format | Should be "£#,###.00"
$ws.cells["e2"].Style.HorizontalAlignment | Should be "Right" $ws.Cells["e2"].Style.HorizontalAlignment | Should be "Right"
} }
} }
Context "Other formatting" { Context "Other formatting" {
it "Trapped an attempt to hide a range instead of a Row/Column " { it "Trapped an attempt to hide a range instead of a Row/Column " {
$BadHideWarnvar | Should not beNullOrEmpty $BadHideWarnvar | Should not beNullOrEmpty
} }
it "Set a row formula with border font size and underline " { it "Set and calculated a row formula with border font size and underline " {
$ws.cells["b7"].style.Border.Top.Style | Should be "None" $ws.Cells["b7"].Style.Border.Top.Style | Should be "None"
$ws.cells["F7"].style.Border.Top.Style | Should be "None" $ws.Cells["F7"].Style.Border.Top.Style | Should be "None"
$ws.cells["C7"].style.Border.Top.Style | Should be "Thin" $ws.Cells["C7"].Style.Border.Top.Style | Should be "Thin"
$ws.cells["C7"].style.Border.Bottom.Style | Should be "Thin" $ws.Cells["C7"].Style.Border.Bottom.Style | Should be "Thin"
$ws.cells["C7"].style.Border.Right.Style | Should be "None" $ws.Cells["C7"].Style.Border.Right.Style | Should be "None"
$ws.cells["C7"].style.Border.Left.Style | Should be "Thin" $ws.Cells["C7"].Style.Border.Left.Style | Should be "Thin"
$ws.cells["E7"].style.Border.Left.Style | Should be "None" $ws.Cells["E7"].Style.Border.Left.Style | Should be "None"
$ws.cells["E7"].style.Border.Right.Style | Should be "Thin" $ws.Cells["E7"].Style.Border.Right.Style | Should be "Thin"
$ws.cells["C7"].style.Font.size | Should be 14 $ws.Cells["C7"].Style.Font.size | Should be 14
$ws.cells["C7"].Formula | Should be "sum(C2:C6)" $ws.Cells["C7"].Formula | Should be "sum(C2:C6)"
$ws.cells["C7"].value | Should be 81 $ws.Cells["C7"].value | Should be 81
$ws.cells["C7"].style.Font.UnderLine | Should be $true $ws.Cells["C7"].Style.Font.UnderLine | Should be $true
$ws.cells["C6"].style.Font.UnderLine | Should be $false $ws.Cells["C6"].Style.Font.UnderLine | Should be $false
} }
it "Set custom text wrapping, alignment, superscript, border and Fill " { it "Set custom font, size, text-wrapping, alignment, superscript, border and Fill " {
$ws.cells["e3"].Style.HorizontalAlignment | Should be "Left" $ws.Cells["b3"].Style.Border.Left.Color.Rgb | Should be "FFFF0000"
$ws.cells["e3"].Style.Font.VerticalAlign | Should be "Superscript" $ws.Cells["b3"].Style.Border.Left.Style | Should be "Thick"
$ws.cells["b3"].style.Border.Left.Color.Rgb | Should be "FFFF0000" $ws.Cells["b3"].Style.Border.Right.Style | Should be "Thick"
$ws.cells["b3"].style.Border.Left.Style | Should be "Thick" $ws.Cells["b3"].Style.Border.Top.Style | Should be "Thick"
$ws.cells["b3"].style.Border.Right.Style | Should be "Thick" $ws.Cells["b3"].Style.Border.Bottom.Style | Should be "Thick"
$ws.cells["b3"].style.Border.Top.Style | Should be "Thick" $ws.Cells["b3"].Style.Font.Strike | Should be $true
$ws.cells["b3"].style.Border.Bottom.Style | Should be "Thick" $ws.Cells["e1"].Style.Font.Color.Rgb | Should be "ff000000"
$ws.cells["b3"].style.Font.Strike | Should be $true $ws.Cells["e1"].Style.Font.Bold | Should be $false
$ws.cells["e1"].Style.Font.Color.rgb | Should be "ff000000" $ws.Cells["e1"].Style.Font.Name | Should be "Courier New"
$ws.cells["e1"].Style.Font.Bold | Should be $false $ws.Cells["e1"].Style.Font.Size | Should be 9
$ws.cells["C6"].style.WrapText | Should be $false $ws.Cells["e3"].Style.Font.VerticalAlign | Should be "Superscript"
$ws.cells["e7"].style.WrapText | Should be $true $ws.Cells["e3"].Style.HorizontalAlignment | Should be "Left"
$ws.cells["e7"].Style.Fill.BackgroundColor.Rgb | Should be "FFF0F8FF" $ws.Cells["C6"].Style.WrapText | Should be $false
$ws.cells["e7"].Style.Fill.PatternColor.Rgb | Should be "FFFF0000" $ws.Cells["e7"].Style.WrapText | Should be $true
$ws.cells["e7"].Style.Fill.PatternType | Should be "DarkTrellis" $ws.Cells["e7"].Style.Fill.BackgroundColor.Rgb | Should be "FFF0F8FF"
$ws.Cells["e7"].Style.Fill.PatternColor.Rgb | Should be "FFFF0000"
$ws.Cells["e7"].Style.Fill.PatternType | Should be "DarkTrellis"
} }
} }
@@ -233,9 +235,9 @@ Describe "Set-ExcelColumn, Set-ExcelRow and Set-ExcelRange" {
$excel = $DriverData | Export-Excel -PassThru -Path $path -AutoSize -AutoNameRange $excel = $DriverData | Export-Excel -PassThru -Path $path -AutoSize -AutoNameRange
$ws = $excel.Workbook.Worksheets[1] $ws = $excel.Workbook.Worksheets[1]
Set-ExcelColumn -Worksheet $ws -Heading "Link" -AutoSize -Value {"https://en.wikipedia.org" + $worksheet.cells["B$Row"].value } Set-ExcelColumn -Worksheet $ws -Heading "Link" -AutoSize -Value {"https://en.wikipedia.org" + $worksheet.Cells["B$Row"].value }
$c = Set-ExcelColumn -PassThru -Worksheet $ws -Heading "NextBirthday" -Value { $c = Set-ExcelColumn -PassThru -Worksheet $ws -Heading "NextBirthday" -Value {
$bmonth = $worksheet.cells["C$Row"].value.month ; $bDay = $worksheet.cells["C$Row"].value.day $bmonth = $worksheet.Cells["C$Row"].value.month ; $bDay = $worksheet.Cells["C$Row"].value.day
$cMonth = [datetime]::Now.Month ; $cday = [datetime]::Now.day ; $cyear = [datetime]::Now.Year $cMonth = [datetime]::Now.Month ; $cday = [datetime]::Now.day ; $cyear = [datetime]::Now.Year
if (($cmonth -gt $bmonth) -or (($cMonth -eq $bmonth) -and ($cday -ge $bDay))){ if (($cmonth -gt $bmonth) -or (($cMonth -eq $bmonth) -and ($cday -ge $bDay))){
[datetime]::new($cyear+1, $bmonth, $bDay) [datetime]::new($cyear+1, $bmonth, $bDay)
@@ -322,7 +324,7 @@ Describe "Table Formatting" {
$excel = $data2 | Export-excel -path $path -WorksheetName Hardware -AutoNameRange -AutoSize -BoldTopRow -FreezeTopRow -PassThru $excel = $data2 | Export-excel -path $path -WorksheetName Hardware -AutoNameRange -AutoSize -BoldTopRow -FreezeTopRow -PassThru
$ws = $excel.Workbook.Worksheets[1] $ws = $excel.Workbook.Worksheets[1]
#test showfilter & TotalSettings #test showfilter & TotalSettings
$Table = Add-ExcelTable -PassThru -Range $ws.cells[$($ws.Dimension.address)] -TableStyle Light1 -TableName HardwareTable -TotalSettings @{"Total"="Sum"} -ShowFirstColumn -ShowFilter:$false $Table = Add-ExcelTable -PassThru -Range $ws.Cells[$($ws.Dimension.address)] -TableStyle Light1 -TableName HardwareTable -TotalSettings @{"Total"="Sum"} -ShowFirstColumn -ShowFilter:$false
#test expnading named number formats #test expnading named number formats
Set-ExcelColumn -Worksheet $ws -Column 4 -NumberFormat 'Currency' Set-ExcelColumn -Worksheet $ws -Column 4 -NumberFormat 'Currency'
Set-ExcelColumn -Worksheet $ws -Column 5 -NumberFormat 'Currency' Set-ExcelColumn -Worksheet $ws -Column 5 -NumberFormat 'Currency'