cp-21keo.ExcelCoordinate.psm1

function ConvertFrom-ExcelCellCoordinate {
    [OutputType([hashtable])]
    param (
        [Parameter(ValueFromPipeline = $true)]
        [string] $InputObject
    )

    process {
        [hashtable] $cell = Expand-ExcelCellCoordinate -InputObject $InputObject
        [int[]] $asciiCodes = Convert-StringToBase26 -InputObject $cell.Column
        $cell.Column = Convert-Base26ToInt -InputObject $asciiCodes

        Write-Output $cell
    }
}

function Expand-ExcelCellCoordinate {
    [OutputType([hashtable])]
    param (
        [Parameter(ValueFromPipeline = $true)]
        [string] $InputObject
    )

    process {
        if ($InputObject -notmatch '^(?<Column>[a-z]{1,3})(?<Row>\d{1,7})$') {
            throw [System.ArgumentException]::new('InputObject should be in format LettersNumbers', 'InputObject')
        }

        [hashtable] $cell = @{
            Row    = [int]$Matches['Row']
            Column = $Matches['Column'].ToUpperInvariant()
        }

        Write-Output $cell
    }
}


function Convert-StringToBase26 {
    [OutputType([int[]])]
    param (
        [Parameter(ValueFromPipeline = $true)]
        [string] $InputObject
    )

    process {
        if ([string]::IsNullOrEmpty($InputObject)) {
            Write-Output (, [int[]]::new(0))
            return
        }

        [int[]] $parts = $InputObject.ToUpperInvariant().ToCharArray()
        $parts = $parts | ForEach-Object { $_ - 64 };

        [Array]::Reverse($parts)

        Write-Output (, $parts)
    }
}

function Convert-Base26ToInt {
    [OutputType([int])]
    param (
        [Parameter(ValueFromPipeline = $true)]
        [int[]] $InputObject
    )

    process {
        [int] $result = 0;

        for ($i = 0; $i -lt $InputObject.Length; $i++) {
            $result += [Math]::Pow(26, $i) * $InputObject[$i]
        }

        Write-Output $result
    }
}