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
- Paste the code into VBA.
- Make sure ArcMap is not in edit mode.
- Select the feature layer that you want to calculate. The calc_VBA routine requires that thelayer have polyline geometry.
- 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.
- Run the sample.
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