Search code examples
functionpowershellvariableshashtable

Powershell hashtable in function not accessible


I created a function to import HR records so they're easily accessible by indexing the employeeID.

function hrDataImport {
$HRFile=Import-Csv $rawHRFile #$rawHRFile path previously defined
Write-Host "Creating HR hash table..."
$hrData = @{}
$HRFile | ForEach-Object { $hrData[$_.employeeID] = $_ }
Write-Host "Done. " $hrData.Count
    }

I'd like to use that $hrData variable outside the function. I can't reference $hrData['employeeID'] as I've read that variables in functions don't exist outside the function. One thing I tried is creating another function to pass an employeeID into the $hrData hashtable:

function showHRData {
    param ([string]$hrUser)
    $hrData[$hrUser]
}

I put the functions in a module and imported successfully. I'm able to execute importHRData fine but when I try showHRData -hrUser $employeeID I get "Cannot index into a null array". Seems like the function does not see the hashtable variable from the previous function. What am I doing wrong or what would you suggest so I can access that $hrData hashtable across various scripts?


Solution

  • You might create a Hashtable within your function using a $global (or $script) scope like this:

    function hrDataImport {
        $HRFile = Import-Csv $rawHRFile #$rawHRFile path previously defined
        Write-Host "Creating HR hash table..."
        if (!$hrData) { $Global:hrData = @{} }
        $HRFile | ForEach-Object { $Global:hrData[$_.employeeID] = $_ }
        Write-Host "Done. " $hrData.Count
    }
    

    But in general it is advised to avoid the global (or script) scope mainly because it might conflict with variables in the current scope.
    To minimize this possibility, I would consider to change the responsibility of your function to not only loading the information but also to receiving the concerned employeeID, e.g.:

    function Get-EmployeeData ($EmployeeID) {
        if (!$StaticEmployeeData) {
            Write-Host "Creating HR hash table..."
            $HRFile = Import-Csv $rawHRFile #$rawHRFile path previously defined
            $Global:StaticEmployeeData = @{}
            $HRFile | ForEach-Object { $Global:StaticEmployeeData[$_.employeeID] = $_ }
            Write-Host "Done. " $StaticEmployeeData.Count
        }
        $Global:StaticEmployeeData[$employeeID]
    }
    
    function showHRData {
        param ([string]$hrUser)
        Get-EmployeeData $hrUser
    }
    

    In that case you might choose for a more specific global variable name (e.g. $StaticEmployeeData, knowing that PowerShell doesn't support something like a static variable) and as an extra bonus the data is only loaded the first time you really need it (lazy evaluation).