Создание / заполнение цикла PSCustomObject для цикла из данных ADO.NET
Я работаю с кучей электронных таблиц Excel, которые имеют от 3 до 14 столбцов:
- У некоторых действительно только 3 колонки
- В некоторых есть несколько скрытых столбцов (например: 5 скрыты, 9 видны)
- Остальные завершены (все данные, без скрытых столбцов и т. Д.) До 14 столбцов
К счастью, во всех случаях мне нужна только часть этих данных, и все они содержат то, что мне нужно. Сначала я хотел прочитать документ Excel и вернуть содержимое в виде объекта, но у меня возникли трудности с концептуализацией процесса, который будет работать для документов Excel с различными столбцами.
Код ниже показывает оба примера, в то время как в реальном мире я бы использовал только один.
Function Get-ExcelContent
{
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$false)]
[string]$ExcelFile,
[Parameter(Mandatory=$false)]
[string]$SheetName,
[alias('Visible')]
[switch]$VisibleFieldsOnly
)
If(!(Test-Path -Path $ExcelFile -PathType Leaf))
{
write-host "Unable to find excel file: $ExcelFile"
break
}
# for 64-bit os'
$strProvider = "Provider=Microsoft.ACE.OLEDB.12.0"
# otherwise 32-bit os
#$strProvider = "Provider=Microsoft.Jet.OLEDB.4.0"
$strDataSource = "Data Source = $ExcelFile"
$strExtend = "Extended Properties=Excel 8.0"
$strQuery = "Select * from [$SheetName]"
$objConn = New-Object System.Data.OleDb.OleDbConnection("$strProvider;$strDataSource;$strExtend")
$sqlCommand = New-Object System.Data.OleDb.OleDbCommand($strQuery)
$sqlCommand.Connection = $objConn
$objConn.open()
$DataReader = $sqlCommand.ExecuteReader()
If($VisibleFieldsOnly)
{
# Get count of the non-hidden fields
$CountOfColumns = $DataReader.VisibleFieldCount
}
Else
{
# Get all the fields
$CountOfColumns = $DataReader.FieldCount
}
$ColumnCounter = 0
$pscoExcelData = @()
While($DataReader.read())
{
###########################################################
# IF I KNOW THE COUNT OF COLUMNS AHEAD OF TIME, THIS WORKS
###########################################################
$pscoExcelData += [pscustomobject][ordered] @{
$DataReader.GetName(0) = $DataReader[0].Tostring()
$DataReader.GetName(1) = $DataReader[1].Tostring()
$DataReader.GetName(2) = $DataReader[2].Tostring()
$DataReader.GetName(3) = $DataReader[3].Tostring()
$DataReader.GetName(4) = $DataReader[4].Tostring()
$DataReader.GetName(5) = $DataReader[5].Tostring()
$DataReader.GetName(6) = $DataReader[6].Tostring()
$DataReader.GetName(7) = $DataReader[7].Tostring()
$DataReader.GetName(8) = $DataReader[8].Tostring()
}
###########################################################
# BUT HOW DO I DO IT WHEN THE COLUMN COUNT VARIES?
###########################################################
for($i=0; $i -le $CountOfColumns-1;$i++)
{
$pscoExcelData += [pscustomobject][ordered] @{ $DataReader.GetName($i) = $DataReader[$i].Tostring() }
}
}
$dataReader.close()
$objConn.close()
$pscoExcelData
}
Get-ExcelData 'C:\path\to\Book1.xlsx' 'Sheet1$' -VisibleFieldsOnly
1 ответ
Вам просто нужно создать хеш-таблицу в цикле, а затем преобразовать ее в объект PowerShell в конце. Что-то вроде следующего (не проверено):
$rec = @{}
for($i=0; $i -lt $CountOfColumns; $i++)
{
$rec[$DataReader.GetName($i)] = $DataReader[$i].Tostring()
}
$pscoExcelData += [pscustomobject][ordered]$rec
Изменить: еще одна возможность, которая должна сохранить порядок столбцов (также не проверено):
$rec = New-Object pscustomobject
for($i=0; $i -lt $CountOfColumns; $i++)
{
$rec | Add-Member -Name $DataReader.GetName($i) -Value $DataReader[$i].Tostring()
}
$pscoExcelData += $rec
(Кстати, это обычное использование -lt
скорее, чем -le
в течение цикла.)