modules/ImportExcel/7.8.9/Public/Import-Excel.ps1
function Import-Excel { [CmdLetBinding()] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "")] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSPossibleIncorrectUsageOfAssignmentOperator', '', Justification = 'Intentional')] param ( [Alias('FullName')] [Parameter(ParameterSetName = "PathA", Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, Position = 0 )] [Parameter(ParameterSetName = "PathB", Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, Position = 0 )] [Parameter(ParameterSetName = "PathC", Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, Position = 0 )] [String[]]$Path, [Parameter(ParameterSetName = "PackageA", Mandatory)] [Parameter(ParameterSetName = "PackageB", Mandatory)] [Parameter(ParameterSetName = "PackageC", Mandatory)] [OfficeOpenXml.ExcelPackage]$ExcelPackage, [Alias('Sheet')] [Parameter(Position = 1)] [ValidateNotNullOrEmpty()] [String[]]$WorksheetName, [Parameter(ParameterSetName = 'PathB' , Mandatory)] [Parameter(ParameterSetName = 'PackageB', Mandatory)] [String[]]$HeaderName , [Parameter(ParameterSetName = 'PathC' , Mandatory)] [Parameter(ParameterSetName = 'PackageC', Mandatory)] [Switch]$NoHeader , [Alias('HeaderRow', 'TopRow')] [ValidateRange(1, 1048576)] [Int]$StartRow = 1, [Alias('StopRow', 'BottomRow')] [Int]$EndRow , [Alias('LeftColumn')] [Int]$StartColumn = 1, [Alias('RightColumn')] [Int]$EndColumn , [Switch]$DataOnly, [string[]]$AsText, [string[]]$AsDate, [ValidateNotNullOrEmpty()] [String]$Password, [Int[]]$ImportColumns, [Switch]$Raw ) end { $sw = [System.Diagnostics.Stopwatch]::StartNew() if ($input) { $Paths = $input } elseif ($Path) { $Paths = $Path } else { $Paths = '' } function Get-PropertyNames { <# .SYNOPSIS Create objects containing the column number and the column name for each of the different header types. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = "Name would be incorrect, and command is not exported")] param( [Parameter(Mandatory)] [Int[]]$Columns, [Parameter(Mandatory)] [Int]$StartRow ) try { if ($ImportColumns) { $end = $sheet.Dimension.End.Column # Check $ImportColumns if ($ImportColumns[0] -le 0) { throw "The first entry in ImportColumns must be equal or greater 1" ; return } # Check $StartColumn and $EndColumn if (($StartColumn -ne 1) -or ($EndColumn -ne $end)) { Write-Warning -Message "If ImportColumns is set, then individual StartColumn and EndColumn will be ignored." } # Replace $Columns with $ImportColumns $Columns = $ImportColumns } if ($HeaderName) { $i = 0 foreach ($H in $HeaderName) { $H | Select-Object @{N = 'Column'; E = { $Columns[$i] } }, @{N = 'Value'; E = { $H } } $i++ } } elseif ($NoHeader) { $i = 0 foreach ($C in $Columns) { $i++ $C | Select-Object @{N = 'Column'; E = { $_ } }, @{N = 'Value'; E = { 'P' + $i } } } } else { if ($StartRow -lt 1) { throw 'The top row can never be less than 1 when we need to retrieve headers from the worksheet.' ; return } foreach ($C in $Columns) { #allow "False" or "0" to be column headings $sheet.Cells[$StartRow, $C] | Where-Object { -not [string]::IsNullOrEmpty($_.Value) } | Select-Object @{N = 'Column'; E = { $C } }, Value } } } catch { throw "Failed creating property names: $_" ; return } } foreach ($Path in $Paths) { if ($path) { $extension = [System.IO.Path]::GetExtension($Path) if ($extension -notmatch '.xlsx$|.xlsm$') { throw "Import-Excel does not support reading this extension type $($extension)" } $resolvedPath = (Resolve-Path $Path -ErrorAction SilentlyContinue) if ($resolvedPath) { $Path = $resolvedPath.ProviderPath } else { throw "'$($Path)' file not found" } $stream = New-Object -TypeName System.IO.FileStream -ArgumentList $Path, 'Open', 'Read', 'ReadWrite' $ExcelPackage = New-Object -TypeName OfficeOpenXml.ExcelPackage if ($Password) { $ExcelPackage.Load($stream, $Password) } else { $ExcelPackage.Load($stream) } } try { #Select worksheet if ($WorksheetName -eq '*') { $Worksheet = $ExcelPackage.Workbook.Worksheets } elseif (-not $WorksheetName) { $Worksheet = $ExcelPackage.Workbook.Worksheets[1] } elseif (-not ($Worksheet = $ExcelPackage.Workbook.Worksheets[$WorksheetName])) { throw "Worksheet '$WorksheetName' not found, the workbook only contains the worksheets '$($ExcelPackage.Workbook.Worksheets)'. If you only wish to select the first worksheet, please remove the '-WorksheetName' parameter." ; return } $xlBook = [Ordered]@{} foreach ($sheet in $Worksheet) { if ($Worksheet.Count -gt 1 -or $Paths.Count -gt 1) { <# Needed under these conditions to handle sheets of different number of Row/Col - When reading more than one xlsx file - When reading more than one worksheet in the same file #> $EndRow = $null $EndColumn = $null } $targetSheetname = $sheet.Name $xlBook["$targetSheetname"] = @() #region Get rows and columns #If we are doing dataonly it is quicker to work out which rows to ignore before processing the cells. if (-not $EndRow ) { $EndRow = $sheet.Dimension.End.Row } if (-not $EndColumn) { $EndColumn = $sheet.Dimension.End.Column } $endAddress = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R[$EndRow]C[$EndColumn]", 0, 0) if ($DataOnly) { #If we are using headers startrow will be the header-row so examine data from startRow + 1, if ($NoHeader) { $range = "A" + ($StartRow ) + ":" + $endAddress } else { $range = "A" + ($StartRow + 1 ) + ":" + $endAddress } #We're going to look at every cell and build 2 hash tables holding rows & columns which contain data. #Want to Avoid 'select unique' operations & large Sorts, becuse time time taken increases with square #of number of items (PS uses heapsort at large size). Instead keep a list of what we have seen, #using Hash tables: "we've seen it" is all we need, no need to worry about "seen it before" / "Seen it many times". $colHash = @{ } $rowHash = @{ } foreach ($cell in $sheet.Cells[$range]) { if ($null -ne $cell.Value ) { $colHash[$cell.Start.Column] = 1; $rowHash[$cell.Start.row] = 1 } } $rows = ( $StartRow..$EndRow ).Where( { $rowHash[$_] }) $columns = ($StartColumn..$EndColumn).Where( { $colHash[$_] }) } else { $Columns = $StartColumn .. $EndColumn ; if ($StartColumn -gt $EndColumn) { Write-Warning -Message "Selecting columns $StartColumn to $EndColumn might give odd results." } if ($NoHeader) { $rows = $StartRow..$EndRow ; if ($StartRow -gt $EndRow) { Write-Warning -Message "Selecting rows $StartRow to $EndRow might give odd results." } } elseif ($HeaderName) { $rows = $StartRow..$EndRow } else { $rows = (1 + $StartRow)..$EndRow if ($StartRow -eq 1 -and $EndRow -eq 1) { $rows = 0 } } # ; if ($StartRow -ge $EndRow) { Write-Warning -Message "Selecting $StartRow as the header with data in $(1+$StartRow) to $EndRow might give odd results." } } } #endregion #region Create property names if ((-not $Columns) -or (-not ($PropertyNames = Get-PropertyNames -Columns $Columns -StartRow $StartRow))) { throw "No column headers found on top row '$StartRow'. If column headers in the worksheet are not a requirement then please use the '-NoHeader' or '-HeaderName' parameter."; return } if ($Duplicates = $PropertyNames | Group-Object Value | Where-Object Count -GE 2) { throw "Duplicate column headers found on row '$StartRow' in columns '$($Duplicates.Group.Column)'. Column headers must be unique, if this is not a requirement please use the '-NoHeader' or '-HeaderName' parameter."; return } #endregion if (-not $rows) { Write-Warning "Worksheet '$WorksheetName' in workbook '$Path' contains no data in the rows after top row '$StartRow'" } else { #region Create one object per row if ($AsText -or $AsDate) { <#join items in AsText together with ~~~ . Escape any regex special characters... # which turns "*" into "\*" make it ".*". Convert ~~~ to $|^ and top and tail with ^%; So if we get "Week", "[Time]" and "*date*" ; make the expression ^week$|^\[Time\]$|^.*Date.*$ $make a regex for this which is case insensitive (option 1) and compiled (option 8) #> $TextColExpression = '' if ($AsText) { $TextColExpression += '(?<astext>^' + [regex]::Escape($AsText -join '~~~').replace('\*', '.*').replace('~~~', '$|^') + '$)' } if ($AsText -and $AsDate) { $TextColExpression += "|" } if ($AsDate) { $TextColExpression += '(?<asDate>^' + [regex]::Escape($AsDate -join '~~~').replace('\*', '.*').replace('~~~', '$|^') + '$)' } $TextColRegEx = New-Object -TypeName regex -ArgumentList $TextColExpression , 9 } else { $TextColRegEx = $null } foreach ($R in $rows) { #Disabled write-verbose for speed # Write-Verbose "Import row '$R'" $NewRow = [Ordered]@{ } if ($TextColRegEx) { foreach ($P in $PropertyNames) { $MatchTest = $TextColRegEx.Match($P.value) if ($MatchTest.groups.name -eq "astext") { $NewRow[$P.Value] = $sheet.Cells[$R, $P.Column].Text } elseif ($MatchTest.groups.name -eq "asdate" -and $sheet.Cells[$R, $P.Column].Value -is [System.ValueType]) { $NewRow[$P.Value] = [datetime]::FromOADate(($sheet.Cells[$R, $P.Column].Value)) } else { $NewRow[$P.Value] = $sheet.Cells[$R, $P.Column].Value } } } else { foreach ($P in $PropertyNames) { $NewRow[$P.Value] = $sheet.Cells[$R, $P.Column].Value # Write-Verbose "Import cell '$($Worksheet.Cells[$R, $P.Column].Address)' with property name '$($p.Value)' and value '$($Worksheet.Cells[$R, $P.Column].Value)'." } } $xlBook["$targetSheetname"] += [PSCustomObject]$NewRow } #endregion } } } catch { throw "Failed importing the Excel workbook '$Path' with worksheet '$WorksheetName': $_"; return } finally { # $EndRow = 0 # $EndColumn = 0 if ($Path) { $stream.close(); $ExcelPackage.Dispose() } if ($Raw) { foreach ($entry in $xlbook.GetEnumerator()) { $entry.Value } } elseif ($Worksheet.Count -eq 1) { $xlBook["$targetSheetname"] } else { $xlBook } } } } } # SIG # Begin signature block # MIIubwYJKoZIhvcNAQcCoIIuYDCCLlwCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCR4Jn+H4tIKcaK # 3SpWPKfhEW6Tz6erPlgZlEcOkVrIuaCCE0cwggVyMIIDWqADAgECAhB2U/6sdUZI # k/Xl10pIOk74MA0GCSqGSIb3DQEBDAUAMFMxCzAJBgNVBAYTAkJFMRkwFwYDVQQK # ExBHbG9iYWxTaWduIG52LXNhMSkwJwYDVQQDEyBHbG9iYWxTaWduIENvZGUgU2ln # bmluZyBSb290IFI0NTAeFw0yMDAzMTgwMDAwMDBaFw00NTAzMTgwMDAwMDBaMFMx # CzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMSkwJwYDVQQD # EyBHbG9iYWxTaWduIENvZGUgU2lnbmluZyBSb290IFI0NTCCAiIwDQYJKoZIhvcN # AQEBBQADggIPADCCAgoCggIBALYtxTDdeuirkD0DcrA6S5kWYbLl/6VnHTcc5X7s # k4OqhPWjQ5uYRYq4Y1ddmwCIBCXp+GiSS4LYS8lKA/Oof2qPimEnvaFE0P31PyLC # o0+RjbMFsiiCkV37WYgFC5cGwpj4LKczJO5QOkHM8KCwex1N0qhYOJbp3/kbkbuL # ECzSx0Mdogl0oYCve+YzCgxZa4689Ktal3t/rlX7hPCA/oRM1+K6vcR1oW+9YRB0 # RLKYB+J0q/9o3GwmPukf5eAEh60w0wyNA3xVuBZwXCR4ICXrZ2eIq7pONJhrcBHe # OMrUvqHAnOHfHgIB2DvhZ0OEts/8dLcvhKO/ugk3PWdssUVcGWGrQYP1rB3rdw1G # R3POv72Vle2dK4gQ/vpY6KdX4bPPqFrpByWbEsSegHI9k9yMlN87ROYmgPzSwwPw # jAzSRdYu54+YnuYE7kJuZ35CFnFi5wT5YMZkobacgSFOK8ZtaJSGxpl0c2cxepHy # 1Ix5bnymu35Gb03FhRIrz5oiRAiohTfOB2FXBhcSJMDEMXOhmDVXR34QOkXZLaRR # kJipoAc3xGUaqhxrFnf3p5fsPxkwmW8x++pAsufSxPrJ0PBQdnRZ+o1tFzK++Ol+ # A/Tnh3Wa1EqRLIUDEwIrQoDyiWo2z8hMoM6e+MuNrRan097VmxinxpI68YJj8S4O # JGTfAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0G # A1UdDgQWBBQfAL9GgAr8eDm3pbRD2VZQu86WOzANBgkqhkiG9w0BAQwFAAOCAgEA # Xiu6dJc0RF92SChAhJPuAW7pobPWgCXme+S8CZE9D/x2rdfUMCC7j2DQkdYc8pzv # eBorlDICwSSWUlIC0PPR/PKbOW6Z4R+OQ0F9mh5byV2ahPwm5ofzdHImraQb2T07 # alKgPAkeLx57szO0Rcf3rLGvk2Ctdq64shV464Nq6//bRqsk5e4C+pAfWcAvXda3 # XaRcELdyU/hBTsz6eBolSsr+hWJDYcO0N6qB0vTWOg+9jVl+MEfeK2vnIVAzX9Rn # m9S4Z588J5kD/4VDjnMSyiDN6GHVsWbcF9Y5bQ/bzyM3oYKJThxrP9agzaoHnT5C # JqrXDO76R78aUn7RdYHTyYpiF21PiKAhoCY+r23ZYjAf6Zgorm6N1Y5McmaTgI0q # 41XHYGeQQlZcIlEPs9xOOe5N3dkdeBBUO27Ql28DtR6yI3PGErKaZND8lYUkqP/f # obDckUCu3wkzq7ndkrfxzJF0O2nrZ5cbkL/nx6BvcbtXv7ePWu16QGoWzYCELS/h # AtQklEOzFfwMKxv9cW/8y7x1Fzpeg9LJsy8b1ZyNf1T+fn7kVqOHp53hWVKUQY9t # W76GlZr/GnbdQNJRSnC0HzNjI3c/7CceWeQIh+00gkoPP/6gHcH1Z3NFhnj0qinp # J4fGGdvGExTDOUmHTaCX4GUT9Z13Vunas1jHOvLAzYIwgga/MIIEp6ADAgECAhEA # gU5CF6Epf+1azNQX+JGtdTANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJCRTEZ # MBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEpMCcGA1UEAxMgR2xvYmFsU2lnbiBD # b2RlIFNpZ25pbmcgUm9vdCBSNDUwHhcNMjQwNjE5MDMyNTExWhcNMzgwNzI4MDAw # MDAwWjBZMQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEv # MC0GA1UEAxMmR2xvYmFsU2lnbiBHQ0MgUjQ1IENvZGVTaWduaW5nIENBIDIwMjAw # ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDWQk3540/GI/RsHYGmMPdI # Pc/Q5Y3lICKWB0Q1XQbPDx1wYOYmVPpTI2ACqF8CAveOyW49qXgFvY71TxkkmXzP # ERabH3tr0qN7aGV3q9ixLD/TcgYyXFusUGcsJU1WBjb8wWJMfX2GFpWaXVS6UNCw # f6JEGenWbmw+E8KfEdRfNFtRaDFjCvhb0N66WV8xr4loOEA+COhTZ05jtiGO792N # hUFVnhy8N9yVoMRxpx8bpUluCiBZfomjWBWXACVp397CalBlTlP7a6GfGB6KDl9U # Xr3gW8/yDATS3gihECb3svN6LsKOlsE/zqXa9FkojDdloTGWC46kdncVSYRmgiXn # Qwp3UrGZUUL/obLdnNLcGNnBhqlAHUGXYoa8qP+ix2MXBv1mejaUASCJeB+Q9Hup # Uk5qT1QGKoCvnsdQQvplCuMB9LFurA6o44EZqDjIngMohqR0p0eVfnJaKnsVahzE # aeawvkAZmcvSfVVOIpwQ4KFbw7MueovE3vFLH4woeTBFf2wTtj0s/y1KiirsKA8t # ytScmIpKbVo2LC/fusviQUoIdxiIrTVhlBLzpHLr7jaep1EnkTz3ohrM/Ifll+FR # h2npIsyDwLcPRWwH4UNP1IxKzs9jsbWkEHr5DQwosGs0/iFoJ2/s+PomhFt1Qs2J # JnlZnWurY3FikCUNCCDx/wIDAQABo4IBhjCCAYIwDgYDVR0PAQH/BAQDAgGGMBMG # A1UdJQQMMAoGCCsGAQUFBwMDMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYE # FNqzjcAkkKNrd9MMoFndIWdkdgt4MB8GA1UdIwQYMBaAFB8Av0aACvx4ObeltEPZ # VlC7zpY7MIGTBggrBgEFBQcBAQSBhjCBgzA5BggrBgEFBQcwAYYtaHR0cDovL29j # c3AuZ2xvYmFsc2lnbi5jb20vY29kZXNpZ25pbmdyb290cjQ1MEYGCCsGAQUFBzAC # hjpodHRwOi8vc2VjdXJlLmdsb2JhbHNpZ24uY29tL2NhY2VydC9jb2Rlc2lnbmlu # Z3Jvb3RyNDUuY3J0MEEGA1UdHwQ6MDgwNqA0oDKGMGh0dHA6Ly9jcmwuZ2xvYmFs # c2lnbi5jb20vY29kZXNpZ25pbmdyb290cjQ1LmNybDAuBgNVHSAEJzAlMAgGBmeB # DAEEATALBgkrBgEEAaAyATIwDAYKKwYBBAGgMgoEAjANBgkqhkiG9w0BAQsFAAOC # AgEAMhDkvBelgxBAndOp/SfPRXKpxR9LM1lvLDIxeXGE1jZn1at0/NTyBjputdbL # 8UKDlr193pUsGu1q40EcpsiJMcJZbIm8KiMDWVBHSf1vUw4qKMxIVO/zIxhbkjZO # vKNj1MP7AA+A0SDCyuWWuvCaW6qkJXoZ2/rbe1NP+baj2WPVdV8BpSjbthgpFGV5 # nNu064iYFFNQYDEMZrNR427JKSZk8BTRc3jEhI0+FKWSWat5QUbqNM+BdkY6kXgZ # c77+BvXXwYQ5oHBMCjUAXtgqMCQfMne24Xzfs0ZB4fptjePjC58vQNmlOg1kyb6M # 0RrJZSA64gD6TnohN0FwmZ1QH5l7dZB0c01FpU5Yf912apBYiWaTZKP+VPdNquvl # IO5114iyHQw8vKGSoFbkR/xnD+p4Kd+Po8fZ4zF4pwsplGscJ10hJ4fio+/IQJAu # XBcoJdMBRBergNp8lKhbI/wgnpuRoZD/sw3lckQsRxXz1JFyJvnyBeMBZ/dptd4F # tv4okIx/oSk7tyzaZCJplsT001cNKoXGu2horIvxUktkbqq4t+xNFBz6qBQ4zuwl # 6+Ri3TX5uHsHXRtDZwIIaz2/JSODgZZzB+7+WFo8N9qg21/SnDpGkpzEJhwJMNol # 5A4dkHPUHodOaYSBkc1lfuc1+oOAatM0HUaneAimeDIlZnowggcKMIIE8qADAgEC # AgxjM0+VRu6w7+lFi6kwDQYJKoZIhvcNAQELBQAwWTELMAkGA1UEBhMCQkUxGTAX # BgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExLzAtBgNVBAMTJkdsb2JhbFNpZ24gR0ND # IFI0NSBDb2RlU2lnbmluZyBDQSAyMDIwMB4XDTI0MDEyNjE1MDcwMVoXDTI1MDEy # NjE1MDcwMVoweDELMAkGA1UEBhMCVVMxDzANBgNVBAgTBk9yZWdvbjEUMBIGA1UE # BxMLTGFrZSBPc3dlZ28xIDAeBgNVBAoTF01pbGVzdG9uZSBTeXN0ZW1zLCBJbmMu # MSAwHgYDVQQDExdNaWxlc3RvbmUgU3lzdGVtcywgSW5jLjCCAiIwDQYJKoZIhvcN # AQEBBQADggIPADCCAgoCggIBANuPJQeA9USbN3zbAcb5W7/1Pc6RnmFcaei4VgjA # oZ90TW2f69uYELwNlwnQAKlTfr9khIMRUVVNIjVwjGeUpDi5u20RaYAwdXs0t3p9 # BnxvgC7kqLXCRP+iKvd1oiFy/WfHwSoHkgr3ZfXW22cfKMRlEBqkOnMnrTvpHNsx # 0BgFt4Uwt+uY5uXoAw0sw28OkBJFBV8BBc+bRqQ+7cwtzmyA7HpNwcC/gFcotOT7 # p9APL6V0K01tZO5JTKephmN1ycQz/SZK6Fbl8Myy0Gla4ZON9gThUVYmNvLEouwo # Vj/7CCAA0Onin3pI9NHDHOu7lJz/N5YGxKQK95WCFrOmcRq5eEJHRN6XGRwzCTMO # nOQ9J8MA9cfxWfzmbOU4jwscTGrXP9ffv3IvdcOkE63cFLBWPja07/qnrCC57mAZ # loGqCJYS1hvvcefIu1AhoAqn1xXnwKLHqW4dAOSorMXjGo6w+0AyV2RgRXkmi+zg # CaOy9Xe9XG449vlJstGU3Mjvr2WrhFFE05hyE7hPPI7EcAm+JXCVBn7yzLIIqsD4 # GgPddMYg9omYQpdKe5eMiJL1jErvxr7aazgcqcgmuIabReqocH36ANVMfoBo140e # PgbAfMJ5gslEPEoo7ArovmXoqs2t62o8SFx/071+dTGYZshlKTpYGZZ9ydpIuuMZ # JSJ/AgMBAAGjggGxMIIBrTAOBgNVHQ8BAf8EBAMCB4AwgZsGCCsGAQUFBwEBBIGO # MIGLMEoGCCsGAQUFBzAChj5odHRwOi8vc2VjdXJlLmdsb2JhbHNpZ24uY29tL2Nh # Y2VydC9nc2djY3I0NWNvZGVzaWduY2EyMDIwLmNydDA9BggrBgEFBQcwAYYxaHR0 # cDovL29jc3AuZ2xvYmFsc2lnbi5jb20vZ3NnY2NyNDVjb2Rlc2lnbmNhMjAyMDBW # BgNVHSAETzBNMEEGCSsGAQQBoDIBMjA0MDIGCCsGAQUFBwIBFiZodHRwczovL3d3 # dy5nbG9iYWxzaWduLmNvbS9yZXBvc2l0b3J5LzAIBgZngQwBBAEwCQYDVR0TBAIw # ADBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vY3JsLmdsb2JhbHNpZ24uY29tL2dz # Z2NjcjQ1Y29kZXNpZ25jYTIwMjAuY3JsMBMGA1UdJQQMMAoGCCsGAQUFBwMDMB8G # A1UdIwQYMBaAFNqzjcAkkKNrd9MMoFndIWdkdgt4MB0GA1UdDgQWBBT3z5hC3BNS # WFzfQByqFmRKy9AYkTANBgkqhkiG9w0BAQsFAAOCAgEAFyXnmIB6a+IH36icvO/L # aNa+Hbz4H6JHst8Lpq9Xefzt8fVMOXMPC163mXHHQjyEXl7qqz++mQgXq9j/gg89 # gIoqP02QE8A23MP4Zqs94lTJfQd1vGN0wts5g87foU366iCxPPGy3d91UmbARdpL # IP5MfCjAZqEBSm1phhOXxFF55QnGfn0rX4MBY63lPm2acgUU+A+36sOyZh1xS9Ec # zsmveTmpx3i6JlGjdmKfxNh91vqHnuHgiMRXradVbkUPih4SLdSw94g3Nj9qYLKk # 2/tHV3fQfwmlgPhW6MUgdUts/UWIwFKhLaVb+BID+asbFVoaOQw1a0Whk/Nd6+CV # H62dExBA/ZxVY6MBfZQk6tU6uWpReEQHJuYqqBr9YOdBYr070SJbyjZWFUdGzGKL # XbpaeSNNxDUf7oaHT2IyHIfrhEykk1mLHoGTZlnRlG3S/v+N3t1FnUhD0Oss3QjA # xQKg3byHCjGevbfajoXMFjLZFKb1cUD7tDctmg4/ZwKar5xdrpgKsXFC3PrCrSbq # 5YqIA9qQ/M6y8wbKVQ/AEdHmaSGOs+Xqq6yQ8+h9jW/QbdhMhj1WWMhEV0wnAy7i # 7Jx6kuramAvS2I8ypu5QlAx3eiAUG4gYOBPXLlGDBz5J1I+Ulggintgy4rXgbNdB # wPGTPWY6QlxM8XNwFnFuDh8xghp+MIIaegIBATBpMFkxCzAJBgNVBAYTAkJFMRkw # FwYDVQQKExBHbG9iYWxTaWduIG52LXNhMS8wLQYDVQQDEyZHbG9iYWxTaWduIEdD # QyBSNDUgQ29kZVNpZ25pbmcgQ0EgMjAyMAIMYzNPlUbusO/pRYupMA0GCWCGSAFl # AwQCAQUAoIGkMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcC # AQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCAp0OFC4dGo+yKQ8JqP # eR0RAfNKO8SFDWSrUsfuFRQ/aDA4BgorBgEEAYI3AgEMMSowKKACgAChIoAgaHR0 # cHM6Ly93d3cubWlsZXN0b25lcHN0b29scy5jb20wDQYJKoZIhvcNAQEBBQAEggIA # YBgZ0sC31oYiU+r5+flC7Tgj6Oa29dC0Fj9u1ZZIALHUwpEmdgRLirB28VwZPSLf # jsTUGr2xYljk5J9W0giYsU/Mz9lxmRB/KLl4itPNdXTF9LiEWPzjzZISqD86FTn8 # ykDerkkpiPH352Xf1hipkjaqYsQ2kBrD01QerFcN6M1vkKjKSu2htpxo9menXAjV # Pno1RXc7kExYDaBNBOKTDTOgsJvhk7AlkTP3QwN7IN0ME/3Cqi+VIIEc21GslytL # XSH5/76O2+Gbh1aNuzwoe4bAZeafuWKe2skUIPhJ+8FcS1URmHxoi0WJZDFf2CJr # 7yiZLCDdS8AzXho04IUh0HFkzO6snUnBYZ1GxXblekRLjE/QHezpxZZ94J2NmYYT # X7illYRl2+MmaWDwMAJKN3pudwCHeGMrWygUr1DaWaUIVrVeZdEArxQXCp0nfIvQ # R6iGDfNO5g5qSLyuYBuCcjjLRehKlHb0mxFgmG9oDsZWiKY4xIvtPum5bTxCnGyV # u+rYlepNr4J0MIhgpyp70nuPwWnQ2IjqOXyEOFvKDj+t+hz3HfwwieGS7TFvS1tM # AkbiSd3+xfcbFzWqoIGIKmjsRlbU6JOelfndy+2/c0/xtJ2UjMHhm5lya+PgaIIX # LILj6OweSehBXq+1GJfBso841E+7CC+xGDHaW4tmZKqhghc/MIIXOwYKKwYBBAGC # NwMDATGCFyswghcnBgkqhkiG9w0BBwKgghcYMIIXFAIBAzEPMA0GCWCGSAFlAwQC # AQUAMHcGCyqGSIb3DQEJEAEEoGgEZjBkAgEBBglghkgBhv1sBwEwMTANBglghkgB # ZQMEAgEFAAQgKnioxyvqOAhY1ru3l822uPRmvIwpd+VL5kJvgQBmKXQCEEW2Xp3u # fwdmUQCppa9p4DMYDzIwMjQwOTI3MDAzNTMyWqCCEwkwggbCMIIEqqADAgECAhAF # RK/zlJ0IOaa/2z9f5WEWMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNVBAYTAlVTMRcw # FQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3Rl # ZCBHNCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0EwHhcNMjMwNzE0MDAw # MDAwWhcNMzQxMDEzMjM1OTU5WjBIMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGln # aUNlcnQsIEluYy4xIDAeBgNVBAMTF0RpZ2lDZXJ0IFRpbWVzdGFtcCAyMDIzMIIC # IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAo1NFhx2DjlusPlSzI+DPn9fl # 0uddoQ4J3C9Io5d6OyqcZ9xiFVjBqZMRp82qsmrdECmKHmJjadNYnDVxvzqX65RQ # jxwg6seaOy+WZuNp52n+W8PWKyAcwZeUtKVQgfLPywemMGjKg0La/H8JJJSkghra # arrYO8pd3hkYhftF6g1hbJ3+cV7EBpo88MUueQ8bZlLjyNY+X9pD04T10Mf2SC1e # RXWWdf7dEKEbg8G45lKVtUfXeCk5a+B4WZfjRCtK1ZXO7wgX6oJkTf8j48qG7rSk # IWRw69XloNpjsy7pBe6q9iT1HbybHLK3X9/w7nZ9MZllR1WdSiQvrCuXvp/k/Xtz # PjLuUjT71Lvr1KAsNJvj3m5kGQc3AZEPHLVRzapMZoOIaGK7vEEbeBlt5NkP4FhB # +9ixLOFRr7StFQYU6mIIE9NpHnxkTZ0P387RXoyqq1AVybPKvNfEO2hEo6U7Qv1z # fe7dCv95NBB+plwKWEwAPoVpdceDZNZ1zY8SdlalJPrXxGshuugfNJgvOuprAbD3 # +yqG7HtSOKmYCaFxsmxxrz64b5bV4RAT/mFHCoz+8LbH1cfebCTwv0KCyqBxPZyS # kwS0aXAnDU+3tTbRyV8IpHCj7ArxES5k4MsiK8rxKBMhSVF+BmbTO77665E42FEH # ypS34lCh8zrTioPLQHsCAwEAAaOCAYswggGHMA4GA1UdDwEB/wQEAwIHgDAMBgNV # HRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMCAGA1UdIAQZMBcwCAYG # Z4EMAQQCMAsGCWCGSAGG/WwHATAfBgNVHSMEGDAWgBS6FtltTYUvcyl2mi91jGog # j57IbzAdBgNVHQ4EFgQUpbbvE+fvzdBkodVWqWUxo97V40kwWgYDVR0fBFMwUTBP # oE2gS4ZJaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0 # UlNBNDA5NlNIQTI1NlRpbWVTdGFtcGluZ0NBLmNybDCBkAYIKwYBBQUHAQEEgYMw # gYAwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBYBggrBgEF # BQcwAoZMaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3Rl # ZEc0UlNBNDA5NlNIQTI1NlRpbWVTdGFtcGluZ0NBLmNydDANBgkqhkiG9w0BAQsF # AAOCAgEAgRrW3qCptZgXvHCNT4o8aJzYJf/LLOTN6l0ikuyMIgKpuM+AqNnn48Xt # JoKKcS8Y3U623mzX4WCcK+3tPUiOuGu6fF29wmE3aEl3o+uQqhLXJ4Xzjh6S2sJA # OJ9dyKAuJXglnSoFeoQpmLZXeY/bJlYrsPOnvTcM2Jh2T1a5UsK2nTipgedtQVyM # adG5K8TGe8+c+njikxp2oml101DkRBK+IA2eqUTQ+OVJdwhaIcW0z5iVGlS6ubzB # aRm6zxbygzc0brBBJt3eWpdPM43UjXd9dUWhpVgmagNF3tlQtVCMr1a9TMXhRsUo # 063nQwBw3syYnhmJA+rUkTfvTVLzyWAhxFZH7doRS4wyw4jmWOK22z75X7BC1o/j # F5HRqsBV44a/rCcsQdCaM0qoNtS5cpZ+l3k4SF/Kwtw9Mt911jZnWon49qfH5U81 # PAC9vpwqbHkB3NpE5jreODsHXjlY9HxzMVWggBHLFAx+rrz+pOt5Zapo1iLKO+ua # gjVXKBbLafIymrLS2Dq4sUaGa7oX/cR3bBVsrquvczroSUa31X/MtjjA2Owc9bah # uEMs305MfR5ocMB3CtQC4Fxguyj/OOVSWtasFyIjTvTs0xf7UGv/B3cfcZdEQcm4 # RtNsMnxYL2dHZeUbc7aZ+WssBkbvQR7w8F/g29mtkIBEr4AQQYowggauMIIElqAD # AgECAhAHNje3JFR82Ees/ShmKl5bMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYT # AlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2Vy # dC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0yMjAz # MjMwMDAwMDBaFw0zNzAzMjIyMzU5NTlaMGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQK # Ew5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBHNCBS # U0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0EwggIiMA0GCSqGSIb3DQEBAQUA # A4ICDwAwggIKAoICAQDGhjUGSbPBPXJJUVXHJQPE8pE3qZdRodbSg9GeTKJtoLDM # g/la9hGhRBVCX6SI82j6ffOciQt/nR+eDzMfUBMLJnOWbfhXqAJ9/UO0hNoR8XOx # s+4rgISKIhjf69o9xBd/qxkrPkLcZ47qUT3w1lbU5ygt69OxtXXnHwZljZQp09ns # ad/ZkIdGAHvbREGJ3HxqV3rwN3mfXazL6IRktFLydkf3YYMZ3V+0VAshaG43IbtA # rF+y3kp9zvU5EmfvDqVjbOSmxR3NNg1c1eYbqMFkdECnwHLFuk4fsbVYTXn+149z # k6wsOeKlSNbwsDETqVcplicu9Yemj052FVUmcJgmf6AaRyBD40NjgHt1biclkJg6 # OBGz9vae5jtb7IHeIhTZgirHkr+g3uM+onP65x9abJTyUpURK1h0QCirc0PO30qh # HGs4xSnzyqqWc0Jon7ZGs506o9UD4L/wojzKQtwYSH8UNM/STKvvmz3+DrhkKvp1 # KCRB7UK/BZxmSVJQ9FHzNklNiyDSLFc1eSuo80VgvCONWPfcYd6T/jnA+bIwpUzX # 6ZhKWD7TA4j+s4/TXkt2ElGTyYwMO1uKIqjBJgj5FBASA31fI7tk42PgpuE+9sJ0 # sj8eCXbsq11GdeJgo1gJASgADoRU7s7pXcheMBK9Rp6103a50g5rmQzSM7TNsQID # AQABo4IBXTCCAVkwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUuhbZbU2F # L3MpdpovdYxqII+eyG8wHwYDVR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08w # DgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMIMHcGCCsGAQUFBwEB # BGswaTAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsG # AQUFBzAChjVodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVz # dGVkUm9vdEc0LmNydDBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdp # Y2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNybDAgBgNVHSAEGTAXMAgG # BmeBDAEEAjALBglghkgBhv1sBwEwDQYJKoZIhvcNAQELBQADggIBAH1ZjsCTtm+Y # qUQiAX5m1tghQuGwGC4QTRPPMFPOvxj7x1Bd4ksp+3CKDaopafxpwc8dB+k+YMjY # C+VcW9dth/qEICU0MWfNthKWb8RQTGIdDAiCqBa9qVbPFXONASIlzpVpP0d3+3J0 # FNf/q0+KLHqrhc1DX+1gtqpPkWaeLJ7giqzl/Yy8ZCaHbJK9nXzQcAp876i8dU+6 # WvepELJd6f8oVInw1YpxdmXazPByoyP6wCeCRK6ZJxurJB4mwbfeKuv2nrF5mYGj # VoarCkXJ38SNoOeY+/umnXKvxMfBwWpx2cYTgAnEtp/Nh4cku0+jSbl3ZpHxcpzp # SwJSpzd+k1OsOx0ISQ+UzTl63f8lY5knLD0/a6fxZsNBzU+2QJshIUDQtxMkzdwd # eDrknq3lNHGS1yZr5Dhzq6YBT70/O3itTK37xJV77QpfMzmHQXh6OOmc4d0j/R0o # 08f56PGYX/sr2H7yRp11LB4nLCbbbxV7HhmLNriT1ObyF5lZynDwN7+YAN8gFk8n # +2BnFqFmut1VwDophrCYoCvtlUG3OtUVmDG0YgkPCr2B2RP+v6TR81fZvAT6gt4y # 3wSJ8ADNXcL50CN/AAvkdgIm2fBldkKmKYcJRyvmfxqkhQ/8mJb2VVQrH4D6wPIO # K+XW+6kvRBVK5xMOHds3OBqhK/bt1nz8MIIFjTCCBHWgAwIBAgIQDpsYjvnQLefv # 21DiCEAYWjANBgkqhkiG9w0BAQwFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMM # RGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQD # ExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMjIwODAxMDAwMDAwWhcN # MzExMTA5MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQg # SW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2Vy # dCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC # AQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEppz1Yq3aaza57G4QNxDAf # 8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9ok3DCsrp1 # mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe # 7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecx # y9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX # 2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX # 9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtmmnTK3kse5w5jrubU75KSOp49 # 3ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7f/LVjHAsQWCq # sWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH # dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauG # i0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo4IBOjCCATYw # DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08w # HwYDVR0jBBgwFoAUReuir/SSy4IxLVGLp6chnfNtyA8wDgYDVR0PAQH/BAQDAgGG # MHkGCCsGAQUFBwEBBG0wazAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNl # cnQuY29tMEMGCCsGAQUFBzAChjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20v # RGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3J0MEUGA1UdHwQ+MDwwOqA4oDaGNGh0 # dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5j # cmwwEQYDVR0gBAowCDAGBgRVHSAAMA0GCSqGSIb3DQEBDAUAA4IBAQBwoL9DXFXn # OF+go3QbPbYW1/e/Vwe9mqyhhyzshV6pGrsi+IcaaVQi7aSId229GhT0E0p6Ly23 # OO/0/4C5+KH38nLeJLxSA8hO0Cre+i1Wz/n096wwepqLsl7Uz9FDRJtDIeuWcqFI # tJnLnU+nBgMTdydE1Od/6Fmo8L8vC6bp8jQ87PcDx4eo0kxAGTVGamlUsLihVo7s # pNU96LHc/RzY9HdaXFSMb++hUD38dglohJ9vytsgjTVgHAIDyyCwrFigDkBjxZgi # wbJZ9VVrzyerbHbObyMt9H5xaiNrIv8SuFQtJ37YOtnwtoeW/VvRXKwYw02fc7cB # qZ9Xql4o4rmUMYIDdjCCA3ICAQEwdzBjMQswCQYDVQQGEwJVUzEXMBUGA1UEChMO # RGlnaUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0ZWQgRzQgUlNB # NDA5NiBTSEEyNTYgVGltZVN0YW1waW5nIENBAhAFRK/zlJ0IOaa/2z9f5WEWMA0G # CWCGSAFlAwQCAQUAoIHRMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAcBgkq # hkiG9w0BCQUxDxcNMjQwOTI3MDAzNTMyWjArBgsqhkiG9w0BCRACDDEcMBowGDAW # BBRm8CsywsLJD4JdzqqKycZPGZzPQDAvBgkqhkiG9w0BCQQxIgQgW3D8tp8j0TGw # ZL62+EthiSssXFBNlsPKCw4Jyx2I1NgwNwYLKoZIhvcNAQkQAi8xKDAmMCQwIgQg # 0vbkbe10IszR1EBXaEE2b4KK2lWarjMWr00amtQMeCgwDQYJKoZIhvcNAQEBBQAE # ggIABN/9/UXRC33SFCA+wQhUKvoHqoZXeA1UMnxu+oYUDX+PrgnyB5jD+h/NG+Ua # enpzDSwrsRx+aSELFXOFLjEoA2WoFqc8ZfSbu1DORr5yG4K0CJqikf/st6ukyOto # 2T1wQH+AjX43iy04i05HnsmB/4CRUDtLfRJbrL4gD7uolyp9hI1FUI1QOlNh6as5 # WGZQgecizh5hUWKfqoLe33vXunn+F2TziR3lv9TkI/l879hXMXTWMLWKQFg5tGtH # jhWtGjzZLwYoNwBTd2P74qqGfJUcCHNdYPtbb4clroKffl9Q3qAEihkBvofNkpyf # bRzP++vWtpyY4P1gp5PLbsjjZ0EnEvVY3MhMyOewCjt2gHo+EZ1stM1SrQHBEsJ9 # 1swC4NYxSQWKswCnqMBWUK0HvRn8zgj0ltaxLkFu2GB/ED2JXq9fpVUOK1fLrzCh # q4/pfwx2CBVMwhSFqchvexwiPOp4XKIeOh6LUDJ/rDvwpPi4PI2u2qccih0YuJsy # 1QTq/Vu1wofUm671KC+wwMkxORISUzMpgvWSz5tGvlL/zk/uVeQ1i4/FCDswwsmN # yMTd2Qm65RpiGAIqM7IY6UDD84O4AtpfHCtXURP7OzmRhx8dkOtUPCDZTL+/W+Xv # YskIh+lHDDaPPgZn4hPd5/x90MAYTrCPjxwM5kWRKCwIwVU= # SIG # End signature block |