Public/Unlock-ExcelPasswordProtection.ps1

<#
.SYNOPSIS
Removes password protection from Excel files (.xlsx, .xlsm) for workbook and/or worksheet.
 
.DESCRIPTION
Unlock-ExcelPasswordProtection extracts, modifies, and repackages Excel files to remove workbook and/or worksheet password protection. Optionally creates a backup before modifying the file.
 
.PARAMETER Path
Path to the Excel file (.xlsx or .xlsm) to unlock.
 
.PARAMETER NoBackup
If specified, skips creation of a backup file before modification.
 
.PARAMETER Remove
Specifies which protection to remove: 'Workbook', 'Worksheet', or 'All'. Default is 'All'.
 
.PARAMETER OutFile
Optional path for the output file. If not specified, overwrites the original file.
 
.EXAMPLE
Unlock-ExcelPasswordProtection -Path 'C:\Files\Protected.xlsx'
Removes all password protection from the specified Excel file and creates a backup.
 
.EXAMPLE
Unlock-ExcelPasswordProtection -Path 'C:\Files\Protected.xlsx' -Remove Workbook -NoBackup
Removes only workbook protection and skips backup creation.
 
.EXAMPLE
Unlock-ExcelPasswordProtection -Path 'C:\Files\Protected.xlsx' -OutFile 'C:\Files\Unlocked.xlsx' -Remove Worksheet
Removes worksheet protection and saves the unlocked file to a new location without modifying the original.
 
.NOTES
Requires PowerShell 5.1 or later. Uses Expand-Archive and Compress-Archive cmdlets.
#>

function Unlock-ExcelPasswordProtection {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, Position = 0)]
        [ValidateNotNullOrEmpty()]
        [string] $Path,

        [Parameter(Mandatory = $false)]
        [switch] $NoBackup = $false,

        [ValidateSet("Workbook", "Worksheet", "All")]
        [string] $Remove = "All",

        [Parameter(Mandatory = $false)]
        [string] $OutFile
    )

    # Implementation of the function goes here
    Write-Verbose "Unlocking Excel password protection for file: $Path"
    
    # convert the file path into a FileInfo object so that it can be properly handled
    $sourceFile = Get-Item -Path $Path

    # validate the file exists and is an Excel file extension
    
    if (-not $sourceFile.Exists) {
        Write-Error "The specified file does not exist: $Path"
        return
    }

    if ($sourceFile.PSIsContainer -and $sourceFile.Extension -ne ".xlsx" -and $sourceFile.Extension -ne ".xlsm") {
        Write-Error "The specified file is not a valid Excel file: $Path"
        return
    }

    # Create a backup if NoBackup is not set
    $backupFileName = $sourceFile.DirectoryName + "\" + $sourceFile.BaseName + ".bak"
    if (-not $NoBackup) {
        Backup-File -Path $sourceFile.FullName -BackupPath $backupFileName
    } else {
        Write-Verbose "Skipping backup creation for file: $Path"
    }

    $tempFolder = $env:TEMP + "\" + [guid]::NewGuid().ToString()
    New-Item -ItemType Directory -Path $tempFolder -Force | Out-Null

    Write-Verbose "Temporary folder created at: $tempFolder"
    try {
        # Unzip the Excel file to the temporary folder
        Expand-Archive -Path $sourceFile.FullName -DestinationPath $tempFolder -Force -Verbose:$false

        # Remove password protection based on the specified option
        if ($Remove -eq "Workbook" -or $Remove -eq "All") {
            Remove-WorkbookProtection -TempPathRoot $tempFolder
        }

        if ($Remove -eq "Worksheet" -or $Remove -eq "All") {
            Remove-WorksheetProtection -TempPathRoot $tempFolder
        }

        # Repackage the Excel file
        $outputFile = if ($OutFile) { $OutFile } else { $sourceFile.FullName }
        Compress-Archive -Path (Join-Path -Path $tempFolder -ChildPath "*") -DestinationPath $outputFile -Force

        Write-Verbose "Excel file unlocked and saved to: $outputFile"
    } catch {
        Write-Error "An error occurred while unlocking the Excel file: $($sourceFile.Name)"
    } finally {
        # Clean up temporary files
        Remove-Item -Path $tempFolder -Recurse -Force
        Write-Verbose "Temporary folder cleaned up."
    }

}