/ / Як примусити тип даних повертатися при запиті Excel з Powershell? - excel, powershell, oledb

Як примусити тип даних повертатися при запиті Excel з Powershell? - excel, powershell, oledb

Я використовую Powershell для запиту електронної таблиці Excel, використовуючи зв'язок OLEDB. У мене є один стовпчик з кількома значеннями в ньому. Я помітив, що коли 1 наша з 4-х кліток містить літери, запит поверне a NULL і тип даних буде a System.DBNull. Дивись нижче:

Excel Spreadsheet 1

Вивід сценарію:

PS D:temp> D:WCC_PowershellExcelTypeTest.ps1 test.xls
Ticket Number: 1 | Type: System.Double
Ticket Number: 2 | Type: System.Double
Ticket Number:  | Type: System.DBNull
Ticket Number: 4 | Type: System.Double

Однак, якщо 2 з 4 комірок містять букви, всі типи даних клітинок повертаються як String. Приклад:

Excel Spreadsheet 2

Вивід сценарію:

PS D:temp> D:WCC_PowershellExcelTypeTest.ps1 test.xls
Ticket Number: 1 | Type: System.String
Ticket Number: ZZZZ | Type: System.String
Ticket Number: AAAA | Type: System.String
Ticket Number: 4 | Type: System.String

Чи є спосіб примусити повернути тип стовпця Excel під час запиту з Powershell? Мій скрипт повинен знати, якщо 1) там є дані (не повертати NULL) і 2) знати тип даних

Ось сценарій Im, що використовується для аналізу документа Excel:

########################################################################################################
# This function will test if a string value is numeric
# Parameters:
#   $value   - String to test
########################################################################################################
function IsNumeric($value) {
return ($($value.Trim()) -match "^[-]?[0-9.]+$")
}

########################################################################################################
# This filter will test if a string value is numeric
# Parameters:
#   $value   - String to test
########################################################################################################
filter isNumeric2() {
return $_ -is [byte]  -or $_ -is [int16]  -or $_ -is [int32]  -or $_ -is [int64]  `
-or $_ -is [sbyte] -or $_ -is [uint16] -or $_ -is [uint32] -or $_ -is [uint64] `
-or $_ -is [float] -or $_ -is [double] -or $_ -is [decimal]
}

# Directory location where we have our excel files
########################################################################################################
$excelFN = "$args"
$ExcelFile = "D:Temp$excelFN"
$Sheetname = "Interface$"

########################################################################################################
$OleDbConn = New-Object “System.Data.OleDb.OleDbConnection”
$OleDbCmd = New-Object “System.Data.OleDb.OleDbCommand”
$OleDbAdapter = New-Object “System.Data.OleDb.OleDbDataAdapter”
$DataTable = New-Object “System.Data.DataTable”
$OleDbConn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=`"$ExcelFile`";Extended Properties=`"Excel 12.0 Xml;HDR=YES`";"
$OleDbConn.Open()
$OleDbCmd.Connection = $OleDbConn
$OleDbCmd.commandtext = “Select * from [$Sheetname]”
$OleDbAdapter.SelectCommand = $OleDbCmd
########################################################################################################

$RowsReturned = $OleDbAdapter.Fill($DataTable)
$intRow = 1
ForEach ($DataRec in $DataTable) {

# Reading the first column of the current row
$TicketNumber = $DataRec."ticket number"

write-host "Ticket Number:" $TicketNumber "| Type:" $TicketNumber.GetType()

$intRow++
}

$OleDbConn.Close()

Відповіді:

1 для відповіді № 1

Відповідно до цього KB Стаття (наголос додано):

Застереження щодо змішаних типів даних

Як зазначалося раніше, ADO повинен здогадатися за данимивведіть для кожного стовпця у вашому аркуші Excel або діапазоні. (Це не впливає на клітинку Excel параметри форматування.) Якщо ви маєте цифрову, виникає серйозна проблема значення, змішані з текстовими значеннями в одному стовпчику. І Джет, і Постачальник ODBC повертає дані типу більшості, але повертає NULL (порожні) значення для типу даних меншин. Якщо це два типи Неодмінно змішується в стовпці, постачальник вибирає числовий текст.

"Безпечний" варіант полягає в тому, щоб обробляти всі поля як текст, додавши IMEX=1 опція для рядка з'єднання:

"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=`"$ExcelFile`";Extended Properties=`"Excel 12.0 Xml;HDR=YES;IMEX=1`";"

а потім перетворити числові значення в сценарій PowerShell, використовуючи явні виклики, такі як:

[int]$value
# or
$value -as [int]

М'який примус за допомогою універсального оператора, такий як:

+$value

або використовуючи статичний аналіз, як це:

[int]::Parse($value)
# or
$numericValue = 0
[int]::TryParse($value,[ref]$numericValue)