GEOG 490/590: GIS Programming

Lab4. ArcMap Layers Display & Attribute Data Manipulation

 

Due Feb 25 before class.

 

Introduction:

 

Hooray! No more ESRI online courses!

You will create a Layers & Attribute Manipulation (LAM) AP that mimics what the instructor demonstrated in class. You should find several small shapefiles to use as test data. The shapefiles must have numerical attribute fields. One good example is the RLIS census track dataset on the I drive. The specifications of the AP follow.

 

Layers & Attribute Manipulation (LAM) Tool:

 

The LAM Tool (Figure 1) allows users to add/delete GIS data layers to/from the active ArcMap map frame. A list box shows the names of the layers that are added to the frame. The order of the items in the list box can be changed and is linked with the display order in ArcMap (Figure 2). Once an item in the layer list is selected, its attribute fields can be displayed in an attribute list box. Users can select a numerical field from the attribute list box to display its minimum, maximum, and average. A sample layout of the UserForm of the AP is shown in Figure 3. The form should have:

l           Two command buttons for adding / removing layers from the display list.

l           Two command buttons for moving a selected layer up and down the display list.

l           Two list boxes for showing the names of map layers and attribute fields.

l           A command button for showing the attribute fields.

l           A command button for calculating the summary statistics of a selected numerical field.

l           Three text box for displaying the minimum, maximum, and average.

l           A command button to clear the layer list and reset the AP.

l           You also need to add labels to annotate the objects on the form.

 

Add Layer Command Button:

You will use the GxDialog object that you used in Lab 3 to select a GIS layer. You need to change the GxObjectFilter type to GxFilterDataset. That is:

 

Dim pFilter As IGxObjectFilter

Set pFilter = New GxFilterDatasets

 

Once the GxDialog object returns a value successfully, you can use the following procedures to display the map.

 

Dim pFLayer As IfeatureLayer

Set pFLayer = New FeatureLayer

Set pFLayer.FeatureClass = pGxDataset.Dataset

pFLayer.Name = pGxDataset.Dataset.Name

   

'add the feature layer to the active map

pMap.AddLayer pFLayer

pMxDoc.ActivatedView.Refresh

 

            You also need to add the name of the layer to the Layer list box. Please note that the AddLayer method of a Map object adds a layer to the top of the TOC (Table of Contents) of the map while the AddItem method of a list box adds an item to the end of the list. One easy way to synchronize the TOC and the list box is, whenever a layer is added or removed, the program resets the list box and displays the updated TOC. The same procedure will be used when the order of the items in the layer list is modified. This is a good reason for us to create a private subroutine to update the list box using map layer information. Add the following code to the UserForm. Please note that you have to declare pMap object variable as a form-level variable (i.e., outside any sub or function) and instantiate it when the UserForm is initialized. Also, the sample code is just for your reference, you must read it carefully and modify it to fit your AP.

 

Private Sub DisplayLayerNames()

    Dim layercounter As Integer

    Dim i As Integer

   

    lstLayer.Clear    'reset the lstLayer list box

 

    'add the layer name to the list box

    layercounter = pMap.LayerCount - 1

    For i = 0 To layercounter

        lstLayer.AddItem pMap.Layer(i).Name

    Next

End Sub

 

            When you need to update the Layer list box, just enter DisplayLayerName in your program. You can find an example of using this subroutine in the Move Down/Up section below.

 

Remove Layer Command Button:

 When a user clicks on an item in the Layer list box, the Remove Layer command button becomes enabled. You will use the DeleteLayer method of a map object to remove a layer. You also need to remove the selected item from the Layer list box. As mentioned earlier, you can use the DisplayLayerNames subroutine to sync the list box, or use the RemoveItem method of a list box to remove the item. You also need to check if there is any layer left in the list box. If none left, then you need to disable the Remove Layer button.

 

    Dim pFLayer As IFeatureLayer

    Set pFLayer = pMap.Layer(lstLayer.ListIndex)

    pMap.DeleteLayer pFLayer

    lstLayer.RemoveItem lstLayer.ListIndex

   

    pMxDoc.ActivatedView.Refresh

 

    If lstLayer.ListCount = 0 Then cmbRemoveLayer.Enabled = False

 

Move Down/Move Up Command Buttons & Layer List Box:

            To use the Move Down/Move Up functions, the user has to select an item from the Layer list box first. Then, depending on which item is selected, the program enables or disables the Move Down or Move Up buttons. The code to control these actions needs to be put in the Click event procedure (i.e., lstLayer_Click(), when the name of the Layer list box is lstLayer.) The ListIndex property of the list box tells you which item in the list is selected. When an item in the Layer list box is selected, the Remove Layer and Show Attribute Fields command buttons are enabled.

 

Private Sub lstLayer_Click()

    cmbShowAtt.Enabled = True

    cmbRemoveLayer.Enabled = True

   

    'don't enable up or down button when there's only one layer

    If lstLayer.ListCount = 1 Then Exit Sub

   

    'enable the down button when the selected layer

'is not the last layer

    If lstLayer.ListIndex < (lstLayer.ListCount - 1) _

Then cmbDown.Enabled = True Else cmbDown.Enabled = False

   

    'enable the up button when the selected layer

'is not the first layer

    If lstLayer.ListIndex > 0 Then cmbUp.Enabled = True _

Else cmbUp.Enabled = False

End Sub

 

The MoveLayer method of a map object allows you to rearrange the display order of a layer in a map object. You will need to know the position the layer is moved to and a pointer that points to the layer that is to be moved. Below is the sample code for the Move Down button. The Move Up button uses the same logic.

 

Private Sub cmbDown_Click()

    Dim position As Long

    position = lstLayer.ListIndex

   

    'assign reference to pFLayer

    Dim pFLayer As IFeatureLayer

    Set pFLayer = pMap.Layer(position)

   

    'swap the layer listbox

    pMap.MoveLayer pFLayer, position + 1

   

    'refresh the active map and the layer list box

    pMxDoc.ActivatedView.Refresh

    DisplayLayerNames

 

    'keep the selected item being selected after the move

    lstLayer.ListIndex = position + 1

End Sub

 

 

Show Attribute Field Command Button:

When the Show Attribute Fields command button is clicked, the names and types of the attribute fields of the select map layer are displayed in the Attribute list box. Please refer to Week5’s lecture notes for retrieving the name and type information of the fields in an attribute table. Check the notes on the IFields and IField interfaces. After you retrieve the field information, use the code below to add them to the Attribute list box.

   

    Dim fcount As Long, i As Long

fcount = pFields.FieldCount - 1

    lstAttList.Clear

 

    For i = 0 To fcount

        Set aField = pFields.Field(i)

        lstAttList.AddItem aField.Name & ", " & aField.Type

    Next

 

Summary Statistics Command Button & Attribute List Box:

The final piece of the LAM AP is finding the minimum and maximum of a selected numerical attribute field and calculating its average value. You have to check if the field you selected is a numerical field. If yes, then you enable the Summary Statistics button. Disable the Summary Statistics button otherwise. You have extracted field type information when creating the Attribute list and stored type information in the list items. You can get the type information from the list items without accessing the attribute table of the map layer. Here is how it’s done in the Click event of the Attribute list box. Please read the code carefully because it contains important information. For example, you should know that when the value of the field type property is smaller then 4 (i.e., 0, 1, 2, and 3), then the field is a numerical field (see lecture note a complete list of field types.)

 

Private Sub lstAttList_Click()

    Dim atttype As Integer

    Dim attstr As String

   

    'check the attribute type

    attstr = lstAttList.List(lstAttList.ListIndex)

   

    'extract the attribute type information from the string

    atttype = Right(attstr, Len(attstr) - InStr(attstr, ","))

   

    'numerical data types are:

'samll integer(0), long integer(1), single(2), and double(3)

    If atttype <= 3 Then

        cmbStats.Enabled = True

        'reset the text in the textbox

        txtMin.Text = ""

        txtMax.Text = ""

        txtAverage.Text = ""

    Else

        cmbStats.Enabled = False

    End If

End Sub

 

Once you have a numerical field selected, the next step is to read the values of its records and find the min/max/mean values. Please refer to Week5’s lecture notes to see how to get the values from an attribute table. You will need to use the ICursor and IFeature interfaces for this task.

You don’t have to store the values you read in an array to find the min/max/mean values. The code below is an example of finding/calculating these numbers. You begin the procedures by setting the minimum (attmin) to the largest number you can get and the maximum (attmax) to the smallest number. A variant type variable (attsum), initialized to 0, holds the sum of all numbers you retrieve from the attribute table. Then use a loop to compare the minimum and maximum with the number you retrieve and add the number to attsum.

 

    Dim attmin, attmax, attsum, tempval

 

    'initialize values

attmin = 2147483647

    attmax = -2147483648#

    attsum = 0

    nrecord = pFLayer.FeatureClass.FeatureCount(Nothing)

   

    Dim aFeature As IFeature

   

    'find min, max, and sum of all values

    For i = 1 To nrecord

        Set aFeature = pCursor.NextFeature

        tempval = aFeature.Value(lstAttList.ListIndex)

        If tempval < attmin Then attmin = tempval

        If tempval > attmax Then attmax = tempval

        attsum = attsum + tempval

    Next

   

    'update output textboxes

    txtMin.Text = Format(attmin, "0.000")

    txtMax.Text = Format(attmax, "0.000")

    txtAverage.Text = Format(attsum / nrecord, "0.000")

 

Clear Map Command Button:

            The Clear Map button removes all layers from the map and reset every control on the UserForm.

 

    'clear layers in the active map frame

    pMap.ClearLayers

   

    'clear the TOC

    pMxDoc.UpdateContents

   

    'refresh the map document

    pMxDoc.ActivatedView.Refresh

 

    'clear attribute and layer lists

    lstAttList.Clear

    lstLayer.Clear

 

Lab Deliverables:

 

Don’t forget to test/debug your AP. Try different ways of using the AP and see if that generates any error or unpredictable behavior. Submit your zipped mxd file. The mxd file must have the following features:

1.          A UserForm and its associated procedures of the LAM AP.

2.          An ArcMap ToolBar containing a button that when clicked brings up the UserForm.

3.          Make sure your code is properly commented.