Be sure to check out my Scripting4Crypto initiative. It’s a fun way to get into using cryptocurrencies all while getting your PowerShell needs met.
Recently, I had created a couple of reports, or rather spreadsheets, and realized this information would be more useful and easier to distribute, read, etc. if it was all contained in one Excel spreadsheet. So, I created a new function, Merge-XLSXWorkbooks using the New-XLSXWorkbook cmdlet available with the PWPS_DAB module.
# Look at the help for New-XLSXWorkbook within PowerShell. Get-Help New-XLSXWorkbook -Full # Look at the help for Merge-XLSXWorkbooks within PowerShell after importing. Get-Help Merge-XLSXWorkbooks -Full
The Merge-XLSXWorkbook allows you a few different methods in which to merge spreadsheets.
First, you can pass a folder path to merge all spreadsheets within the folder.
# Pass a path and output filename Merge-XLSXWorkbooks -Path 'D:\Projects' -OutputFileName 'ConsolidatedReport.xlsx' -Verbose # Include the -Open switch parameter to open Excel once the new spreadsheet is created.Merge-XLSXWorkbooks -Path 'D:\Projects' -OutputFileName 'ConsolidatedReport.xlsx' -Open -Verbose # Include the -Overwrite switch parameter to replace the output file if it already exists.Merge-XLSXWorkbooks -Path 'D:\Projects' -OutputFileName 'ConsolidatedReport.xlsx' -Overwrite -Verbose
Second, you can supply multiple spreadsheets to be merged together into a new spreadsheet.
# Using splatting for readability. $MergeFileInfo = @{ Path = 'D:\!Projects' Spreadsheets = 'SourceSpreadsheet_01.xlsx', 'SourceSpreadsheet_02.xlsx' OutputFileName = 'ConsolidatedReport.xlsx' } # Include the -Overwrite switch parameter to overwrite the output file if it already exists. And include the -Open switch parameter to open the output file once created. Merge-XLSXWorkBooks @MergeFileInfo -OverWrite -Open -Verbose
Give this a try and let me know what you think. Hopefully, you find it useful.
CODE:
FUNCTION Merge-XLSXWorkbooks { <# .SYNOPSIS Merge multiple Excel Spreadsheets into a new spreadsheet. .DESCRIPTION Merges specified spreadsheets or all spreadsheet within a specified folder. There is an option to overwrite if the output file exists. .EXAMPLE Merge-XLSXWorkBooks -Path 'D:\!Projects' -OutputFileName 'ConsolidatedReport.xlsx' -Open In this example, all spreadsheets contained in the !Projects folder with be combined into the ConsolidatedReport.xlsx file. The new spreadsheet will be opened once created. .EXAMPLE # Using splatting for readability. $MergeFileInfo = @{ Path = 'D:\!Projects' Spreadsheets = 'Production_Report.xlsx', 'Production_Template Report_FoldersContainingDocuments.xlsx' OutputFileName = 'ConsolidatedReport.xlsx' } Merge-XLSXWorkBooks @MergeFileInfo -OverWrite -Verbose In this example, only the two specified spreadsheets will be merged into the new 'ConsolidatedReport.xlsx'. If the outputfile exists within the specified folder, it will be overwritten. #> [CmdletBinding()] param ( [ValidateScript({ Test-Path -Path $_ })] [Parameter(Mandatory=$true, Position=0)] [System.String] $Path, [Parameter(Mandatory=$false, Position=1)] [System.String[]] $Spreadsheets, [Parameter(Mandatory=$true, Position=2)] [System.String] $OutputFileName, [Parameter(Mandatory=$false)] [switch] $OverWrite, [Parameter(Mandatory=$false)] [switch] $Open ) BEGIN{ } # end BEGIN PROCESS { try { Write-Verbose -Message "[PROCESS] Getting all Excel file (xlsx, xls) objects from folder '$Path'." $ChildItems = Get-ChildItem -Path $Path -Filter '*.xls*' -File -ErrorAction Stop if($ChildItems) { Write-Verbose -Message ("[PROCESS] {0} documents returned." -f $ChildItems.Count) } else { Write-Warning -Message "[PROCESS] No documents returned." } } catch { Write-Error -Message ("[PROCESS] {0}" -f $error[0].Exception.Message) } # end try/catch if($ChildItems) { Write-Verbose -Message "[PROCESS] Creating new list to store datatable objects." $dtArray = @() #New-Object System.Collections.ArrayList # Counter for the progress bar. $Count = 1 Write-Verbose -Message "[PROCESS] Looping through all childitems found." foreach ($ChildItem in $ChildItems) { $percentComplete = $(($Count / $ChildItems.Count) * 100 ) $Progress = @{ Activity = "Getting information for '$($ChildItem.Name)'." Status = "Processing $Count of $($ChildItems.Count)" PercentComplete = $([math]::Round($percentComplete, 2)) } Write-Progress @Progress -CurrentOperation ChildItems # If spreadsheets are included, determine if the $childitem name is contained in the spreadsheets variable. # if not, continue to the next childitem. if($SpreadSheets) { if(-not ($Spreadsheets.Contains($ChildItem.Name))){ continue } } Write-Verbose -Message ("[PROCESS] Importing worksheets from {0}." -f "$Path\$($ChildItem.Name)") $dtFromExcel = Get-TablesFromXLSXWorkbook -InputFileName "$Path\$($ChildItem.Name)" Write-Verbose -Message ("[PROCESS] Imported {0} tables from {1}." -f $dtFromExcel.Count, $ChildItem.Name) Write-Verbose -Message ("[PROCESS] Adding {0} datatables to the list." -f $dtFromExcel.Count) $dtArray += $dtFromExcel Write-Verbose -Message ("[PROCESS] Removing {0} variable." -f $dtFromExcel) Remove-Variable dtFromExcel } # end foreach ($ChildItem... $CreateNewFile = $true Write-Verbose -Message ("Determine if outputfile '{0}' exists." -f $OutputFileName) if(Test-Path -Path "$Path\$OutputFileName" -PathType Leaf -Verbose) { if($OverWrite) { Write-Warning -Message ("Outputfile '{0}' already exists in folder '{1}'. Overwrite is set, therefore existing file will be deleted." -f $OutputFileName, $Path) Remove-Item -Path "$Path\$OutputFileName" -Force -Verbose } else { Write-Warning -Message ("Outputfile '{0}' already exists in folder '{1}'. Overwrite is not set, therefore file will not be created." -f $OutputFileName, $Path) $CreateNewFile = $false } } if($CreateNewFile) { try { Write-Verbose -Message ("[PROCESS] Preparing to export {0} datatables to {1}." -f $dtArray.Count, $("$Path\$OutputFileName")) New-XLSXWorkbook -InputTables $dtArray -OutputFileName "$Path\$OutputFileName" -Open:$Open -ErrorAction Stop } catch { Write-Error -Message ("[PROCESS] {0}" -f $error[0].Exception.Message) } # end try/catch } } # end if } # end PROCESS END{ } # end PROCESS } # end FUNCTION