无法从有序字典中获取数据
Can't get data out of ordered dictionary
我正在尝试从我订购的字典中获取数据,但由于某种原因它没有打印其中的数据。我可以到达数据结构中的第一项,但我无法遍历所有行。我正在使用 PowerShell 5.1 和 visual studio 代码。
代码查询一个mdb文件,returns多行。
Function ProcessHelpMDB{
[cmdletbinding()]
Param ([string]$mdbLookupError, [string]$mdbFilePath, [string]$mdbPrinterSeries)
Process
{
$adOpenStatic = 3
$adLockOptimistic = 3
$deviceTable = $mdbPrinterSeries + "PP"
$mdbLookupError -Match '[0-9]*-([0-9]*)'
$errLookup = $Matches[1]
$selectQuery = “SELECT [$($deviceTable)].[HelpCode],
[$($deviceTable)].[ScreenNumber],
[$($deviceTable)].[TextID],
[$($deviceTable)].[PictureID]
FROM [$($deviceTable)]
WHERE
[$($deviceTable)].[HelpCode] = $($errLookup)"
$cn = new-object -comobject ADODB.Connection
$rs = new-object -comobject ADODB.Recordset
$cn.Open("Provider = Microsoft.ACE.OLEDB.16.0;Data Source = $mdbFilePath")
$rs.Open($selectQuery,
$cn, $adOpenStatic, $adLockOptimistic)
$i=0
$ret = [ordered]@{}
if($rs.EOF)
{
Write-Host "$mdbLookupString not in $mdbFileName...record set returned emtpy for query"
}#if
else
{
while($rs.EOF -ne $True)
{
$result = [ordered]@{}
foreach ($field in $rs.Fields)
{
$result[$field.name] = $field.Value
}#result
$newObject = [PSCustomObject]$result
$ret.Add($i,$newObject) ###ordered dictionary needs key to add values
$i++
$rs.MoveNext()
} #while
Write-Host "retArr[] $($ret)" #prints retArr[] System.Collections.Specialized.OrderedDictionary
Write-Host "retArr[0] $($ret[0,"TextID"])" #prints retArr[0]
Write-Host "retArr[0] $($ret[0])" #prints retArr[0] @{PictureID=HELP_BLAH; TextID=HELP_INFO; HelpCode=9; ScreenNumber=1}
foreach($row in $ret)
{
foreach($item in $row.value) #it's skipping these
{
Write-Host $item #
Write-Host $item[0] #
Write-Host $item[0].'TextID' #
Write-Host $item.'TextID' #
}#foreach
}
$cn.Close()
return $ret
} #end Process
}# End of Function process mdb's
mdb 中的数据看起来像这样 table:
HelpCode ScreenNumber TextID PictureID
1000 1 HELP_INFO HELP_BLAH
1000 2 HELP_INFO2 HELP_BLAH2
...
我的问题是,如何从数据结构中打印出table中的数据?稍后我需要访问它以将其与其他数据重新组合成一个字符串。我的问题是我不知道如何访问每一行。在数据结构中,每行中的每个项目都是单独的。我似乎知道如何访问第一行,但不知道如何访问其他行。
我最近一直在看这个:looping over hash table
更新:
我得到 TextID
来打印 ret
的每一行,如下面的评论..谢谢!!:
foreach($row in $ret.GetEnumerator()) #this is working for each row, using
{
Write-Host $row.TextID #prints nothing
Write-Host $row.'TextID' #prints nothing
Write-Host $($row.TextID) #prints nothing
Write-Host $($row.'TextID') #prints nothing
Write-Host $($row[0].TextID) #prints nothing
Write-Host $($row[0].'TextID') #prints nothing
Write-Host $($row[0].Value.TextID) #prints TextID value of current row
Write-Host $($row[0].Value.'TextID') #prints TextID value of current row
}
更新2:
我正在尝试改进以下答案中建议的数据结构。谢谢!!这是一个很好的简化。
$ret = [System.Collections.Generic.List[psobject]]::new() #different data struc
if($rs.EOF)
{
Write-Host "$mdbLookupString not in $mdbFileName...record set returned emtpy for query"
}#if
else
{
while($rs.EOF -ne $True)
{
$result = [ordered]@{}
foreach ($field in $rs.Fields)
{
$result[$field.name] = $field.Value
}#result
$newObject = [PSCustomObject]$result
$ret.Add($newObject) ###
$rs.MoveNext()
} #while
}#else
Write-Host "retArr[] $($ret)" #prints retArr[]
Write-Host "retArr[0] $($ret[0,"TextID"])" #prints retArr[0]
Write-Host "retArr[0] $($ret[0])" #prints retArr[0] @{PictureID=...; TextID=...; HelpCode=9; ScreenNumber=1}
$i=0
foreach($row in $ret) #goes thru all rows
{
Write-Host "retArr[] $($ret)" #prints retArr[]
Write-Host "retArr[0] $($ret[$i,"TextID"])" #prints retArr[0] @{HelpCode=9; ScreenNumber=1; TextID=...; PictureID=...}
Write-Host "retArr[0] $($ret[$i].TextID)" #prints retArr[0] HELP_...
Write-Host "retArr[0] $($ret[$i].'TextID')" #retArr[0] HELP_...
####
Write-Host "retArr[] $($row)" #prints retArr[] @{HelpCode=9; ScreenNumber=1; TextID=...; PictureID=HELP_...}
Write-Host "retArr[0] $($row[$i,"TextID"])" #prints retArr[0]
Write-Host "retArr[0] $($row[$i])" #prints retArr[0] @{HelpCode=9; ScreenNumber=1; TextID=HELP_...; PictureID=HELP_...}
Write-Host "retArr[0] $($row[$i].TextID)" #prints retArr[0] HELP_...
Write-Host "retArr[0] $($row[$i].'TextID')" #retArr[0] HELP_...
$i++
}
foreach($row in $ret.GetEnumerator()) #this is working for each row
{
Write-Host $row.TextID #prints HELP_...
Write-Host $row.'TextID' #prints HELP_...
Write-Host $($row.TextID) #prints HELP_...
Write-Host $($row.'TextID') #prints HELP_...
Write-Host $($row[0].TextID) #HELP_...
Write-Host $($row[0].'TextID') #HELP_...
Write-Host $($row[0].Value.TextID) #prints nothing
Write-Host $($row[0].Value.'TextID') #prints nothing
}
效果很好。感谢@mathias 的帮助!
更新3:
我正在尝试@iRon 评论中的管道想法,使用 update2(优化的数据结构):
$ret | ForEach-Object {
Write-Host TextID= $($_.TextID) #prints TextID= HELP_...
Write-Host TextID= $($_.'TextID') #prints TextID= HELP_...
Write-Host TextID= $($_.Value.TextID) #prints TextID=
Write-Host TextID= $($_.Value.'TextID') #prints TextID=
}
谢谢艾伦!这是访问数据结构中数据的好方法。 :)
您可以通过显式调用 GetEnumerator()
并将生成的枚举器传递给 foreach
或 pipeline-enabled cmdlet 来遍历字典中的每个 key-value 条目:
foreach($kvp in $ret.GetEnumerator())
{
Write-Host "Key: $($kvp.Key) - Value: $($kvp.Value)"
}
也就是说,只要您使用连续的整数作为键,您也可以使用 list 而不是字典:
# create a list instead of a dictionary
$ret = [System.Collections.Generic.List[psobject]]::new()
# ...
while($rs.EOF -ne $True)
{
$result = [ordered]@{}
foreach ($field in $rs.Fields)
{
$result[$field.name] = $field.Value
}
$newObject = [PSCustomObject]$result
$ret.Add($newObject) # add object to list, no need to keep track of `$i` here.
$rs.MoveNext()
}
# ...
列表与数组一样可索引,因此您可以:
$ret[4] # this will get you the 5th row
我正在尝试从我订购的字典中获取数据,但由于某种原因它没有打印其中的数据。我可以到达数据结构中的第一项,但我无法遍历所有行。我正在使用 PowerShell 5.1 和 visual studio 代码。
代码查询一个mdb文件,returns多行。
Function ProcessHelpMDB{
[cmdletbinding()]
Param ([string]$mdbLookupError, [string]$mdbFilePath, [string]$mdbPrinterSeries)
Process
{
$adOpenStatic = 3
$adLockOptimistic = 3
$deviceTable = $mdbPrinterSeries + "PP"
$mdbLookupError -Match '[0-9]*-([0-9]*)'
$errLookup = $Matches[1]
$selectQuery = “SELECT [$($deviceTable)].[HelpCode],
[$($deviceTable)].[ScreenNumber],
[$($deviceTable)].[TextID],
[$($deviceTable)].[PictureID]
FROM [$($deviceTable)]
WHERE
[$($deviceTable)].[HelpCode] = $($errLookup)"
$cn = new-object -comobject ADODB.Connection
$rs = new-object -comobject ADODB.Recordset
$cn.Open("Provider = Microsoft.ACE.OLEDB.16.0;Data Source = $mdbFilePath")
$rs.Open($selectQuery,
$cn, $adOpenStatic, $adLockOptimistic)
$i=0
$ret = [ordered]@{}
if($rs.EOF)
{
Write-Host "$mdbLookupString not in $mdbFileName...record set returned emtpy for query"
}#if
else
{
while($rs.EOF -ne $True)
{
$result = [ordered]@{}
foreach ($field in $rs.Fields)
{
$result[$field.name] = $field.Value
}#result
$newObject = [PSCustomObject]$result
$ret.Add($i,$newObject) ###ordered dictionary needs key to add values
$i++
$rs.MoveNext()
} #while
Write-Host "retArr[] $($ret)" #prints retArr[] System.Collections.Specialized.OrderedDictionary
Write-Host "retArr[0] $($ret[0,"TextID"])" #prints retArr[0]
Write-Host "retArr[0] $($ret[0])" #prints retArr[0] @{PictureID=HELP_BLAH; TextID=HELP_INFO; HelpCode=9; ScreenNumber=1}
foreach($row in $ret)
{
foreach($item in $row.value) #it's skipping these
{
Write-Host $item #
Write-Host $item[0] #
Write-Host $item[0].'TextID' #
Write-Host $item.'TextID' #
}#foreach
}
$cn.Close()
return $ret
} #end Process
}# End of Function process mdb's
mdb 中的数据看起来像这样 table:
HelpCode ScreenNumber TextID PictureID
1000 1 HELP_INFO HELP_BLAH
1000 2 HELP_INFO2 HELP_BLAH2
...
我的问题是,如何从数据结构中打印出table中的数据?稍后我需要访问它以将其与其他数据重新组合成一个字符串。我的问题是我不知道如何访问每一行。在数据结构中,每行中的每个项目都是单独的。我似乎知道如何访问第一行,但不知道如何访问其他行。
我最近一直在看这个:looping over hash table
更新:
我得到 TextID
来打印 ret
的每一行,如下面的评论..谢谢!!:
foreach($row in $ret.GetEnumerator()) #this is working for each row, using
{
Write-Host $row.TextID #prints nothing
Write-Host $row.'TextID' #prints nothing
Write-Host $($row.TextID) #prints nothing
Write-Host $($row.'TextID') #prints nothing
Write-Host $($row[0].TextID) #prints nothing
Write-Host $($row[0].'TextID') #prints nothing
Write-Host $($row[0].Value.TextID) #prints TextID value of current row
Write-Host $($row[0].Value.'TextID') #prints TextID value of current row
}
更新2: 我正在尝试改进以下答案中建议的数据结构。谢谢!!这是一个很好的简化。
$ret = [System.Collections.Generic.List[psobject]]::new() #different data struc
if($rs.EOF)
{
Write-Host "$mdbLookupString not in $mdbFileName...record set returned emtpy for query"
}#if
else
{
while($rs.EOF -ne $True)
{
$result = [ordered]@{}
foreach ($field in $rs.Fields)
{
$result[$field.name] = $field.Value
}#result
$newObject = [PSCustomObject]$result
$ret.Add($newObject) ###
$rs.MoveNext()
} #while
}#else
Write-Host "retArr[] $($ret)" #prints retArr[]
Write-Host "retArr[0] $($ret[0,"TextID"])" #prints retArr[0]
Write-Host "retArr[0] $($ret[0])" #prints retArr[0] @{PictureID=...; TextID=...; HelpCode=9; ScreenNumber=1}
$i=0
foreach($row in $ret) #goes thru all rows
{
Write-Host "retArr[] $($ret)" #prints retArr[]
Write-Host "retArr[0] $($ret[$i,"TextID"])" #prints retArr[0] @{HelpCode=9; ScreenNumber=1; TextID=...; PictureID=...}
Write-Host "retArr[0] $($ret[$i].TextID)" #prints retArr[0] HELP_...
Write-Host "retArr[0] $($ret[$i].'TextID')" #retArr[0] HELP_...
####
Write-Host "retArr[] $($row)" #prints retArr[] @{HelpCode=9; ScreenNumber=1; TextID=...; PictureID=HELP_...}
Write-Host "retArr[0] $($row[$i,"TextID"])" #prints retArr[0]
Write-Host "retArr[0] $($row[$i])" #prints retArr[0] @{HelpCode=9; ScreenNumber=1; TextID=HELP_...; PictureID=HELP_...}
Write-Host "retArr[0] $($row[$i].TextID)" #prints retArr[0] HELP_...
Write-Host "retArr[0] $($row[$i].'TextID')" #retArr[0] HELP_...
$i++
}
foreach($row in $ret.GetEnumerator()) #this is working for each row
{
Write-Host $row.TextID #prints HELP_...
Write-Host $row.'TextID' #prints HELP_...
Write-Host $($row.TextID) #prints HELP_...
Write-Host $($row.'TextID') #prints HELP_...
Write-Host $($row[0].TextID) #HELP_...
Write-Host $($row[0].'TextID') #HELP_...
Write-Host $($row[0].Value.TextID) #prints nothing
Write-Host $($row[0].Value.'TextID') #prints nothing
}
效果很好。感谢@mathias 的帮助!
更新3: 我正在尝试@iRon 评论中的管道想法,使用 update2(优化的数据结构):
$ret | ForEach-Object {
Write-Host TextID= $($_.TextID) #prints TextID= HELP_...
Write-Host TextID= $($_.'TextID') #prints TextID= HELP_...
Write-Host TextID= $($_.Value.TextID) #prints TextID=
Write-Host TextID= $($_.Value.'TextID') #prints TextID=
}
谢谢艾伦!这是访问数据结构中数据的好方法。 :)
您可以通过显式调用 GetEnumerator()
并将生成的枚举器传递给 foreach
或 pipeline-enabled cmdlet 来遍历字典中的每个 key-value 条目:
foreach($kvp in $ret.GetEnumerator())
{
Write-Host "Key: $($kvp.Key) - Value: $($kvp.Value)"
}
也就是说,只要您使用连续的整数作为键,您也可以使用 list 而不是字典:
# create a list instead of a dictionary
$ret = [System.Collections.Generic.List[psobject]]::new()
# ...
while($rs.EOF -ne $True)
{
$result = [ordered]@{}
foreach ($field in $rs.Fields)
{
$result[$field.name] = $field.Value
}
$newObject = [PSCustomObject]$result
$ret.Add($newObject) # add object to list, no need to keep track of `$i` here.
$rs.MoveNext()
}
# ...
列表与数组一样可索引,因此您可以:
$ret[4] # this will get you the 5th row