Private/ComputerListParser.ps1

function Get-ComputersFromFile {
    <#
    .SYNOPSIS
        Parses computer names from various file formats.
     
    .DESCRIPTION
        Supports .txt, .csv, and .xlsx files. For CSV and Excel files, allows
        specifying a column name using the format: filepath:columnname
     
    .PARAMETER FilePath
        Path to the file, optionally with :columnname suffix for CSV/Excel files.
     
    .EXAMPLE
        Get-ComputersFromFile -FilePath 'servers.txt'
     
    .EXAMPLE
        Get-ComputersFromFile -FilePath 'servers.csv:ComputerName'
     
    .EXAMPLE
        Get-ComputersFromFile -FilePath 'servers.xlsx:HostName'
    #>

    [CmdletBinding()]
    [OutputType([string[]])]
    param(
        [Parameter(Mandatory)]
        [string]$FilePath
    )
    
    try {
        # Parse file path and column name
        $columnName = $null
        $actualPath = $FilePath
        
        if ($FilePath -match '^(.+?):([\w]+)$') {
            $actualPath = $Matches[1]
            $columnName = $Matches[2]
            Write-Verbose "Parsed file path: '$actualPath', column: '$columnName'"
        }
        
        # Validate file exists
        if (-not (Test-Path -Path $actualPath -PathType Leaf)) {
            throw "File not found: $actualPath"
        }
        
        $extension = [System.IO.Path]::GetExtension($actualPath).ToLower()
        $computers = @()
        
        switch ($extension) {
            '.txt' {
                Write-Verbose "Reading computers from text file: $actualPath"
                $computers = Get-Content -Path $actualPath |
                    Where-Object { $_ -and $_.Trim() -and -not $_.StartsWith('#') } |
                    ForEach-Object { $_.Trim() }
            }
            
            '.csv' {
                Write-Verbose "Reading computers from CSV file: $actualPath"
                $csvData = Import-Csv -Path $actualPath
                
                if ($columnName) {
                    # Use specified column
                    if (-not ($csvData | Get-Member -Name $columnName -MemberType NoteProperty)) {
                        throw "Column '$columnName' not found in CSV. Available columns: $($csvData[0].PSObject.Properties.Name -join ', ')"
                    }
                    $computers = $csvData | ForEach-Object { $_.$columnName } | Where-Object { $_ }
                    Write-Verbose "Extracted $($computers.Count) computers from column '$columnName'"
                }
                else {
                    # No column specified - use first column
                    $firstColumn = $csvData[0].PSObject.Properties.Name[0]
                    $computers = $csvData | ForEach-Object { $_.$firstColumn } | Where-Object { $_ }
                    Write-Verbose "No column specified, using first column '$firstColumn': $($computers.Count) computers"
                }
            }
            
            { $_ -in '.xlsx', '.xls' } {
                Write-Verbose "Reading computers from Excel file: $actualPath"
                
                # Require ImportExcel module
                if (-not (Get-Module -ListAvailable -Name ImportExcel)) {
                    throw "ImportExcel module is required to read Excel files. Install it with: Install-Module ImportExcel"
                }
                
                Import-Module ImportExcel -ErrorAction Stop
                
                $excelData = Import-Excel -Path $actualPath
                
                if ($columnName) {
                    # Use specified column
                    if (-not ($excelData | Get-Member -Name $columnName -MemberType NoteProperty)) {
                        throw "Column '$columnName' not found in Excel file. Available columns: $($excelData[0].PSObject.Properties.Name -join ', ')"
                    }
                    $computers = $excelData | ForEach-Object { $_.$columnName } | Where-Object { $_ }
                    Write-Verbose "Extracted $($computers.Count) computers from column '$columnName'"
                }
                else {
                    # No column specified - use first column
                    $firstColumn = $excelData[0].PSObject.Properties.Name[0]
                    $computers = $excelData | ForEach-Object { $_.$firstColumn } | Where-Object { $_ }
                    Write-Verbose "No column specified, using first column '$firstColumn': $($computers.Count) computers"
                }
            }
            
            default {
                throw "Unsupported file format: $extension. Supported formats: .txt, .csv, .xlsx, .xls"
            }
        }
        
        # Clean up computer names
        $computers = $computers | ForEach-Object { $_.ToString().Trim() } | Where-Object { $_ }
        
        Write-Verbose "Successfully loaded $($computers.Count) computers from file"
        return $computers
    }
    catch {
        Write-Error "Failed to read computers from file '$FilePath': $_"
        throw
    }
}