src/Excel/Read-XrmExcelSheet.ps1
|
<# .SYNOPSIS Read Excel Sheet. .DESCRIPTION Read a worksheet and return a collection of objects using the header row as property names. Use -AsArray to keep the legacy raw Excel array behavior. .PARAMETER ExcelFilePath Full path to Excel file. .PARAMETER SheetName Excel sheet name. .PARAMETER HeaderRowIndex Excel row number that contains the column headers. Default is 1. .PARAMETER AsArray Return the raw Excel value array instead of PSCustomObject rows. #> function Read-XrmExcelSheet { [CmdletBinding()] [OutputType([PSCustomObject[]])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidateScript({ Test-Path $_ })] [String] $ExcelFilePath, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $SheetName, [Parameter(Mandatory = $false)] [ValidateRange(1, [int]::MaxValue)] [int] $HeaderRowIndex = 1, [Parameter(Mandatory = $false)] [switch] $AsArray = $false ) begin { $StopWatch = [System.Diagnostics.Stopwatch]::StartNew(); Trace-XrmFunction -Name $MyInvocation.MyCommand.Name -Stage Start -Parameters ($MyInvocation.MyCommand.Parameters); } process { $workbook = $null; $sheet = $null; $sheetContentRange = $null; $excelApplication = New-Object -ComObject Excel.Application; try { $excelApplication.Visible = $false; $excelApplication.ScreenUpdating = $false; $excelApplication.DisplayAlerts = 'False'; $workbook = $excelApplication.Workbooks.Open($ExcelFilePath); $sheet = $workbook.Sheets | Where-Object -Property Name -EQ -Value $SheetName | Select-Object -First 1; if ($null -eq $sheet) { throw "Excel sheet '$SheetName' was not found in '$ExcelFilePath'."; } $sheetContentRange = $sheet.UsedRange; $sheetValuesArray = $sheetContentRange.Value2; if ($AsArray) { return , $sheetValuesArray; } $rowCount = [int]$sheetContentRange.Rows.Count; $columnCount = [int]$sheetContentRange.Columns.Count; if ($rowCount -lt $HeaderRowIndex) { throw "Excel sheet '$SheetName' does not contain header row $HeaderRowIndex."; } if ($null -eq $sheetValuesArray) { return @(); } $headerNames = @(); $headerNamesCount = @{}; for ($columnIndex = 1; $columnIndex -le $columnCount; $columnIndex++) { if ($sheetValuesArray -is [System.Array]) { $headerValue = $sheetValuesArray[$HeaderRowIndex, $columnIndex]; } else { $headerValue = $sheetValuesArray; } $headerName = [string]$headerValue; if ([string]::IsNullOrWhiteSpace($headerName)) { $headerName = "Column$columnIndex"; } if ($headerNamesCount.ContainsKey($headerName)) { $headerNamesCount[$headerName]++; $headerName = "$headerName$($headerNamesCount[$headerName])"; } else { $headerNamesCount[$headerName] = 1; } $headerNames += $headerName; } $rows = @(); for ($rowIndex = ($HeaderRowIndex + 1); $rowIndex -le $rowCount; $rowIndex++) { $row = [ordered]@{}; $hasValue = $false; for ($columnIndex = 1; $columnIndex -le $columnCount; $columnIndex++) { $cellValue = $sheetValuesArray[$rowIndex, $columnIndex]; if ($null -ne $cellValue -and -not [string]::IsNullOrWhiteSpace([string]$cellValue)) { $hasValue = $true; } $row[$headerNames[$columnIndex - 1]] = $cellValue; } if ($hasValue) { $rows += [PSCustomObject]$row; } } return $rows; } finally { try { if ($null -ne $workbook) { $workbook.Close(); } } catch { # Ignore } try { $excelApplication.DisplayAlerts = 'False'; $excelProcess = Get-Process Excel | Where-Object { $_.MainWindowHandle -eq $excelApplication.Hwnd } $excelApplication.Quit(); if ($null -ne $sheetContentRange) { [void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($sheetContentRange); } if ($null -ne $sheet) { [void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($sheet); } if ($null -ne $workbook) { [void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($workbook); } [void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($excelApplication); [GC]::Collect(); [GC]::WaitForPendingFinalizers(); if ($null -ne $excelProcess) { Stop-Process -Id $excelProcess.Id; } } catch { # Ignore } } } end { $StopWatch.Stop(); Trace-XrmFunction -Name $MyInvocation.MyCommand.Name -Stage Stop -StopWatch $StopWatch; } } Export-ModuleMember -Function Read-XrmExcelSheet -Alias *; |