Select to view content in your preferred language

DataStatistics Interface and System.Collection.IEnumerator

919
9
05-19-2010 08:37 AM
RuchiraWelikala
Regular Contributor
Hi All,
The code below retrieves attributes from a shapefile and attempts to put them into a combobox. 
The majority of the code works fine, but towards the end, where the "value" object is declared is where things go wrong.  The pEnumVar should be returning the next value in the row it's looking at, but instead it gets a Boolean value (True or False).  It would be great if someone could post some feedback regarding this issue.
Thanks for your time,
Ruchira Welikala

 Public Sub Sort_Unique(ByVal pLayer As IFeatureLayer, ByVal fieldname As String, ByVal condition As IQueryFilter)

        Dim pTable As ITable
        Dim pTableSort As ITableSort
        Dim sFieldName As String = fieldname
        Dim pCursor As ICursor


        Dim i As Integer
        For i = 0 To pMap.LayerCount - 1
            If pMap.Layer(i).Name = "Lots Improved" Then
                pLayer = pMap.Layer(i)
                ' pWellLayer = pLayer
            End If
        Next

        ' Gets the attribute table from the passed layer
        pTable = pLayer.FeatureClass

        ' This example sorts the specificed field name
        pTableSort = New TableSort
        With pTableSort
            .Fields = sFieldName
            .Ascending(sFieldName) = True
            .Table = pTable
        End With

        ' sort the table
        pTableSort.Sort(Nothing)

        ' Loop through sorted records and add to a listbox
        pCursor = pTableSort.Rows

        Dim pData As IDataStatistics
        pData = New DataStatistics
        pData.Field = fieldname
        pCursor = pLayer.Search(condition, False)
        pData.Cursor = pCursor
        Dim pEnumVar As System.Collections.IEnumerator
        Dim value As Object

        pEnumVar = pData.UniqueValues
        value = pEnumVar.MoveNext

        For i = 0 To pData.UniqueValueCount - 1
            cmbLot.Items.Add(value)
            value = pEnumVar.MoveNext
        Next
End Sub
0 Kudos
9 Replies
JamesCrandall
MVP Alum
To get the unique value string for pEnumVar, setup a String Variable and set it to .Current. Something like:

Dim val As String
For i = 0 To pData.UniqueValueCount - 1
      value = pEnumVar.MoveNext
      val = CStr(pEnumVar.Current) '<--- this will give you the string value of pEnumVar
Next





Hi All,
The code below retrieves attributes from a shapefile and attempts to put them into a combobox. 
The majority of the code works fine, but towards the end, where the "value" object is declared is where things go wrong.  The pEnumVar should be returning the next value in the row it's looking at, but instead it gets a Boolean value (True or False).  It would be great if someone could post some feedback regarding this issue.
Thanks for your time,
Ruchira Welikala

 Public Sub Sort_Unique(ByVal pLayer As IFeatureLayer, ByVal fieldname As String, ByVal condition As IQueryFilter)

        Dim pTable As ITable
        Dim pTableSort As ITableSort
        Dim sFieldName As String = fieldname
        Dim pCursor As ICursor


        Dim i As Integer
        For i = 0 To pMap.LayerCount - 1
            If pMap.Layer(i).Name = "Lots Improved" Then
                pLayer = pMap.Layer(i)
                ' pWellLayer = pLayer
            End If
        Next

        ' Gets the attribute table from the passed layer
        pTable = pLayer.FeatureClass

        ' This example sorts the specificed field name
        pTableSort = New TableSort
        With pTableSort
            .Fields = sFieldName
            .Ascending(sFieldName) = True
            .Table = pTable
        End With

        ' sort the table
        pTableSort.Sort(Nothing)

        ' Loop through sorted records and add to a listbox
        pCursor = pTableSort.Rows

        Dim pData As IDataStatistics
        pData = New DataStatistics
        pData.Field = fieldname
        pCursor = pLayer.Search(condition, False)
        pData.Cursor = pCursor
        Dim pEnumVar As System.Collections.IEnumerator
        Dim value As Object

        pEnumVar = pData.UniqueValues
        value = pEnumVar.MoveNext

        For i = 0 To pData.UniqueValueCount - 1
            cmbLot.Items.Add(value)
            value = pEnumVar.MoveNext
        Next
End Sub
0 Kudos
JamesCrandall
MVP Alum
I went ahead and just added the necessary line of code to populate the CboBox

 Public Sub Sort_Unique(ByVal pLayer As IFeatureLayer, ByVal fieldname As String, ByVal condition As IQueryFilter)

        Dim pTable As ITable
        Dim pTableSort As ITableSort
        Dim sFieldName As String = fieldname
        Dim pCursor As ICursor


        Dim i As Integer
        For i = 0 To pMap.LayerCount - 1
            If pMap.Layer(i).Name = "Lots Improved" Then
                pLayer = pMap.Layer(i)
                ' pWellLayer = pLayer
            End If
        Next

        ' Gets the attribute table from the passed layer
        pTable = pLayer.FeatureClass

        ' This example sorts the specificed field name
        pTableSort = New TableSort
        With pTableSort
            .Fields = sFieldName
            .Ascending(sFieldName) = True
            .Table = pTable
        End With

        ' sort the table
        pTableSort.Sort(Nothing)

        ' Loop through sorted records and add to a listbox
        pCursor = pTableSort.Rows

        Dim pData As IDataStatistics
        pData = New DataStatistics
        pData.Field = fieldname
        pCursor = pLayer.Search(condition, False)
        pData.Cursor = pCursor
        Dim pEnumVar As System.Collections.IEnumerator
        Dim value As Object

        pEnumVar = pData.UniqueValues
        value = pEnumVar.MoveNext

        For i = 0 To pData.UniqueValueCount - 1
            cmbLot.Items.Add(CStr(pEnumVar.Current)) '<--- this should add the values to your cmbLot Control
            value = pEnumVar.MoveNext
        Next
End Sub
0 Kudos
RuchiraWelikala
Regular Contributor
That did it!  Thanks James!  Can't believe I was simply missing one crucial line! 
I'm attempting to convert code from VBA to VB.NET and that's why I ran into this little problem!

Thanks again!
0 Kudos
JamesCrandall
MVP Alum
That did it!  Thanks James!  Can't believe I was simply missing one crucial line! 
I'm attempting to convert code from VBA to VB.NET and that's why I ran into this little problem!

Thanks again!


Glad I could help.  Good luck on your conversion project!

Take Care
0 Kudos
RuchiraWelikala
Regular Contributor
Glad I could help.  Good luck on your conversion project!

Take Care


Sorry to bug you again James, but I ran into another snag. 
The code below is the same code as above except that I've now modified it so that everything works properly and it's a function rather than a procedure.  I return the array to a combo box as seen on the second snippet of code. 
The thing is, when I run the ArcMap application, I get the following error:   "Value Cannot be null.  Parameter name: item." then This is in the Exception Text.
[HTML]************** Exception Text **************
System.ArgumentNullException: Value cannot be null.
Parameter name: item
   at System.Windows.Forms.ComboBox.ObjectCollection.AddInternal(Object item)
   at System.Windows.Forms.ComboBox.ObjectCollection.AddRangeInternal(IList items)
   at System.Windows.Forms.ComboBox.ObjectCollection.AddRange(Object[] items)
   at MappingTools.ZTL.cmbTownship_SelectedIndexChanged(Object sender, EventArgs e) in C:\Users\Ruchira\Desktop\PetroGISdotNET\MappingTools\ZoomToLot\ZTL.vb:line 255
   at System.Windows.Forms.ComboBox.OnSelectedIndexChanged(EventArgs e)
   at System.Windows.Forms.ComboBox.WmReflectCommand(Message& m)
   at System.Windows.Forms.ComboBox.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)[/HTML]

Public Function Sort_Unique(ByVal pLayer As IFeatureLayer, ByVal fieldname As String, _
                                ByVal condition As IQueryFilter)

        Dim pTable As ITable
        Dim pTableSort As ITableSort
        Dim sFieldName As String = fieldname
        Dim pCursor As ICursor
        Dim MyArray() As String
        ReDim MyArray(0)

        ' Gets the attribute table from the passed layer
        pTable = pLayer.FeatureClass

        ' This example sorts the specificed field name
        pTableSort = New TableSort
        With pTableSort
            .Fields = sFieldName
            .Ascending(sFieldName) = True
            .Table = pTable
        End With

        ' sort the table
        pTableSort.Sort(Nothing)

        ' Loop through sorted records and add to a listbox
        pCursor = pTableSort.Rows

        Dim pData As IDataStatistics
        pData = New DataStatistics
        pData.Field = fieldname
        pCursor = pLayer.Search(condition, False)
        pData.Cursor = pCursor
        Dim pEnumVar As System.Collections.IEnumerator
        Dim value As Object
        Dim strval As String
        pEnumVar = pData.UniqueValues
        value = pEnumVar.MoveNext
        strval = CStr(pEnumVar.Current)

        For i = 0 To pData.UniqueValueCount - 1
            If strval <> " " Then
                strval = CStr(pEnumVar.Current)
                MyArray(i) = strval
                ReDim Preserve MyArray(i + 1)
                value = pEnumVar.MoveNext
            End If
        Next

        Sort_Unique = MyArray
End Function


        'Call function Sort_Unique and populate the Lot combo box
        cmbLot.Items.AddRange(Sort_Unique(pFLayer, fieldname, pFilter))
0 Kudos
JamesCrandall
MVP Alum
Redo the if statement to include an IsDbNull...

Instead of:

If strval <> " " Then

Use:

If Not IsDBNull(strval) Then
0 Kudos
RuchiraWelikala
Regular Contributor
Redo the if statement to include an IsDbNull...

Instead of:

If strval <> " " Then

Use:

If Not IsDBNull(strval) Then


Hmm, still getting the same error.  I even moved the:

value = pEnumVar.MoveNext

outside the if statement.  I also manually checked the attribute table of the shapefile, and yes, there are null values.  But the if statement should omit those.
0 Kudos
JamesCrandall
MVP Alum
I am away from the office, but you can try this until I return tomorrow:

     For i = 0 To pData.UniqueValueCount - 1
            If Not IsDbBull(CStr(pEnumVar.Current)) Then 
                strval = CStr(pEnumVar.Current)
                MyArray(i) = strval
                ReDim Preserve MyArray(i + 1)
                value = pEnumVar.MoveNext
            End If
      Next
0 Kudos
RuchiraWelikala
Regular Contributor
I am away from the office, but you can try this until I return tomorrow:

     For i = 0 To pData.UniqueValueCount - 1
            If Not IsDbBull(CStr(pEnumVar.Current)) Then 
                strval = CStr(pEnumVar.Current)
                MyArray(i) = strval
                ReDim Preserve MyArray(i + 1)
                value = pEnumVar.MoveNext
            End If
      Next


Thanks a lot for all your help James! I think I figured it out.  I tried this out before trying your code and it seemed to do the job. 
        ' For loop that populates the array
        For i = 0 To pData.UniqueValueCount - 1
            strval = CStr(pEnumVar.Current)
            If Not IsDBNull(strval) Then
                MyArray(i) = strval
                ' If the for loop is at the last value, then the loop is terminated
                If i = pData.UniqueValueCount - 1 Then
                    Exit For
                End If
                ReDim Preserve MyArray(i + 1)
            End If
            value = pEnumVar.MoveNext
        Next


Thanks again.
0 Kudos