How to calculate values


This sample demonstrates how to perform a calculation outside of an edit session. Calculations done outside of an edit session are normally faster then calculations within an edit session, but there is no way to undo the changes.
The first routine performs a simple calculation where all records in an integer field are set to 10. The second rountine uses VBA to determine the length of each feature and writes this value to the appropriate row in the table. Note the alternative pre-expression which can be used to get the length in data frame units. The last routine is a function which is called by the first 2 routines. It returns True if the data you are using can be edited outside of an edit session. This sample mimics the behavior of the calculate values command in the column context menu of the table window.
To see how to perform calculations within an edit session, see the examples in the help for the ICalculator and ICalculatorCallback Interfaces.

How to use

  1. Paste the code into VBA.
  2. Make sure ArcMap is not in edit mode.
  3. Select the feature layer that you want to calculate. The calc_VBA routine requires that thelayer have polyline geometry.
  4. For the calc_Simple script, make sure that a short field named shortfld is in the selectedlayer. The calc_VBA script also requires a double field named len. Alternatively, you can adjust the scripts to use different field names.
  5. Run the sample.
[VBA]
Public Sub calc_Simple()
    
    On Error GoTo EH
    
    Dim pDoc As IMxDocument
    Set pDoc = ThisDocument
    
    ' Get the layer that is selected in the TOC
    ' it must be a polygon layer
    Dim pFeatLayer As IFeatureLayer
    Dim pFeatClass As IFeatureClass
    Dim pUnKnown As IUnknown
    Set pUnKnown = pDoc.SelectedLayer
    If pUnKnown Is Nothing Then
        MsgBox "Must have a layer selected in the table of contents."
        Exit Sub
    End If
    Set pFeatLayer = pUnKnown
    Set pFeatClass = pFeatLayer.FeatureClass
    
    ' This calculation is to be done outside of an edit session.
    Dim pEditor As IEditor
    Dim pID As New UID
    pID = "esriEditor.Editor"
    Set pEditor = Application.FindExtensionByCLSID(pID)
    If pEditor.EditState = esriStateEditing Then
        MsgBox "This sample requires that ArcMap is not in edit mode"
        Exit Sub
    End If
    
    ' Also, check to see if the selected layer supports editing without
    ' an edit session
    If Not CanEditWOEditSession(pFeatClass) Then
        MsgBox "This layer cannot be edited outside of an edit session"
        Exit Sub
    End If
    
    ' Find the field named AreaCalc
    Dim pCalc As ICalculator
    Dim pTable As ITable
    Dim pField As IField
    Dim intFldIndex As Integer
    Set pTable = pFeatClass
    intFldIndex = pTable.FindField("shortfld")
    If intFldIndex = -1 Then
        MsgBox "There must be a field named AreaCalc in the layer"
        Exit Sub
    End If
    
    ' Perform the calculation. Make sure to use an update cursor when
    ' editing outside of an edit session.
    Dim pCursor As ICursor
    Set pCalc = New Calculator
    Set pCursor = pFeatClass.Update(Nothing, True)
    
    With pCalc
        Set .Cursor = pCursor
        .Expression = "10"
        .Field = "shortfld"
    End With
    pCalc.Calculate
    
    Exit Sub
EH:
    
    MsgBox Err.Number & "  " & Err.Description
    
End Sub

Public Sub calc_VBA()
    
    On Error GoTo EH
    
    Dim pDoc As IMxDocument
    Set pDoc = ThisDocument
    
    ' Get the layer that is selected in the TOC
    ' it must be a line layer
    Dim pFeatLayer As IFeatureLayer
    Dim pFeatClass As IFeatureClass
    Dim pUnKnown As IUnknown
    Set pUnKnown = pDoc.SelectedLayer
    If pUnKnown Is Nothing Then
        MsgBox "Must have a line layer selected in the table of contents."
        Exit Sub
    End If
    Set pFeatLayer = pUnKnown
    Set pFeatClass = pFeatLayer.FeatureClass
    If Not pFeatClass.ShapeType = esriGeometryPolyline Then
        MsgBox "Selected layer must be a line layer"
        Exit Sub
    End If
    
    ' This calculation is to be done outside of an edit session.
    Dim pEditor As IEditor
    Dim pID As New UID
    pID = "esriEditor.Editor"
    Set pEditor = Application.FindExtensionByCLSID(pID)
    If pEditor.EditState = esriStateEditing Then
        MsgBox "This sample requires that ArcMap is not in edit mode"
        Exit Sub
    End If
    
    ' Also, check to see if the selected layer supports editing without
    ' an edit session
    If Not CanEditWOEditSession(pFeatClass) Then
        MsgBox "This layer cannot be edited outside of an edit session"
        Exit Sub
    End If
    
    ' Find the fields named x and y
    Dim pCalc As ICalculator
    Dim pTable As ITable
    Dim pField As IField
    Dim intFldIndex As Integer
    Set pTable = pFeatClass
    intFldIndex = pTable.FindField("len")
    If intFldIndex = -1 Then
        MsgBox "There must be a field named len in the layer"
        Exit Sub
    End If
    
    ' Perform the calculation
    '
    '  To get the length using the unit of measure for the
    '  data frame, replace the pre-expression with the code below
    '
    '      .PreExpression = "Dim pMxDoc As esriarcmapui.IMxDocument" & vbNewLine & _
    '        "Dim pGeometry As esrigeometry.IGeometry" & vbNewLine & _
    '        "Dim pMap As esricarto.IMap" & vbNewLine & _
    '        "Dim pCurve As esrigeometry.ICurve" & vbNewLine & _
    '        "Dim dblLength As Double" & vbNewLine & _
    '        "Set pMxDoc = ThisDocument" & vbNewLine & _
    '        "Set pMap = pMxDoc.FocusMap" & vbNewLine & _
    '        "If (IsNull([Shape])) Then" & vbNewLine & _
    '        "  dblLength = -1" & vbNewLine & _
    '        "Else" & vbNewLine & _
    '        "  Set pGeometry = [Shape]" & vbNewLine & _
    '        "  If (pGeometry.IsEmpty) Then" & vbNewLine & _
    '        "    dblLength = -1" & vbNewLine & _
    '        "  Else" & vbNewLine & _
    '        "    pGeometry.Project pMap.SpatialReference" & vbNewLine & _
    '        "    Set pCurve = pGeometry" & vbNewLine & _
    '        "    dblLength = pCurve.Length" & vbNewLine & _
    '        "  End If" & vbNewLine & _
    '        "End If"
    
    Set pCalc = New Calculator
    Dim pCursor As ICursor
    Set pCursor = pFeatClass.Update(Nothing, True)
    With pCalc
        Set .Cursor = pCursor
        .PreExpression = "Dim dblLength as double" & vbNewLine & _
                         "Dim pCurve As esrigeometry.ICurve" & vbNewLine & _
                         "Set pCurve = [Shape]" & vbNewLine & _
                         "dblLength = pCurve.Length"
        .Expression = "dblLength"
        .Field = "len"
    End With
    pCalc.Calculate
    Set pCursor = Nothing
    
    Exit Sub
EH:
    
    MsgBox Err.Number & "  " & Err.Description
    
End Sub

' Returns TRUE if the Table can be edited outside of an edit session

Private Function CanEditWOEditSession(pTable As ITable) As Boolean
    
    Dim pVersionedObject As IVersionedObject
    Dim pObjClassInfo2 As IObjectClassInfo2
    Dim bolVersioned As Boolean
    Dim bolEditable As Boolean
    
    ' See if the data is versioned
    If Not TypeOf pTable Is IVersionedObject Then
        bolVersioned = False
    Else
        Set pVersionedObject = pTable
        bolVersioned = pVersionedObject.IsRegisteredAsVersioned
    End If
    
    ' Check the CanBypassEditSession property
    Set pObjClassInfo2 = pTable
    bolEditable = pObjClassInfo2.CanBypassEditSession
    
    If bolEditable And Not bolVersioned Then
        CanEditWOEditSession = True
    Else
        CanEditWOEditSession = False
    End If
    
End Function