Select to view content in your preferred language

Programmatically using Field Calculator to update XY co-ordinates with ArcGIS 10

3795
5
Jump to solution
04-27-2012 11:05 AM
NathanSykes
Emerging Contributor
My company is going through the process of upgrading our software to ArcGIS 10.0 from 9.3.1, half the machines are now at 10.0 and half are still on 9.3.1.  I'm in the process of upgrading all our VBA code to VB.NET and add-ins.

My current problem is with calling the Field Calculator programmatically.  With 9.3.1 I was able to use ArcObjects in the pre-expression to define a shape and extract the X or Y co-ordinates.  I know that with 10.0 the VBA has been retired and I now have the choice of VB Script or Python.  If I have the attribute table open and directly use the Field Calculator, the Python line !shape.extent.XMax! does exactly what I want.

Is there any way I can get this to work in the VB.NET code that I am using with the add-in.  I can call the calculator but I think I've seen that it's a known bug that you can't define what parser will be used in the calculator, thus defaulting to VB Script (which I don't think will extract/identify the X/Y co-ordinate - but correct me if I'm wrong).

Any help with this would be greatly appreciated.
0 Kudos
1 Solution

Accepted Solutions
KenBuja
MVP Esteemed Contributor
Apparently the way around the bug is to use the GeoProcessing tool CalculateField, which does have the ability to select the parser. Here's how I use the tool in one of my projects

    Public Sub CalculateField(ByVal InputTable As Object, ByVal FieldName As String, ByVal Expression As String, Optional ByVal ExpressionType As String = Nothing, Optional ByVal CodeBlock As String = Nothing, Optional ByVal Output As Object = Nothing)          Dim Calc As New ESRI.ArcGIS.DataManagementTools.CalculateField         Dim Result As ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult2          Try             Using releaser As New ESRI.ArcGIS.ADF.ComReleaser                 releaser.ManageLifetime(Calc)                  Calc.in_table = InputTable                 Calc.field = FieldName                 Calc.expression = Expression                 Calc.expression_type = ExpressionType 'VB, PYTHON, or PYTHON_9.3                 Calc.code_block = CodeBlock                 Calc.out_table = Output                  Result = RunTool(Calc, Nothing)                 If Result Is Nothing Then                     System.Windows.Forms.MessageBox.Show("Could not calculate field")                 End If             End Using         Catch ex As Exception             System.Windows.Forms.MessageBox.Show(ex.ToString, "Calculate Field error")         End Try      End Sub  Friend Function RunTool(ByVal Process As ESRI.ArcGIS.Geoprocessor.IGPProcess, ByVal TC As ESRI.ArcGIS.esriSystem.ITrackCancel) As ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult          Dim Result As ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult          Try             System.Windows.Forms.Cursor.Current = Windows.Forms.Cursors.WaitCursor                          Dim GP As New ESRI.ArcGIS.Geoprocessor.Geoprocessor              Result = CType(GP.Execute(Process, Nothing), ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult)             If Result.Status <> ESRI.ArcGIS.esriSystem.esriJobStatus.esriJobSucceeded Then                 If GP.MessageCount > 0 Then                     For Count = 0 To Globals.GP.MessageCount - 1                         Message += GP.GetMessage(Count) & vbNewLine                     Next                     System.Windows.Forms.MessageBox.Show(Message, "GP Failure")                 End If                               Return Nothing             End If             Return Result         Catch ex As Exception             System.Windows.Forms.MessageBox.Show(ex.ToString & vbNewLine & ex.StackTrace, "Run Geoprocessor")             Return Nothing         End Try      End Function

View solution in original post

0 Kudos
5 Replies
KenBuja
MVP Esteemed Contributor
Apparently the way around the bug is to use the GeoProcessing tool CalculateField, which does have the ability to select the parser. Here's how I use the tool in one of my projects

    Public Sub CalculateField(ByVal InputTable As Object, ByVal FieldName As String, ByVal Expression As String, Optional ByVal ExpressionType As String = Nothing, Optional ByVal CodeBlock As String = Nothing, Optional ByVal Output As Object = Nothing)          Dim Calc As New ESRI.ArcGIS.DataManagementTools.CalculateField         Dim Result As ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult2          Try             Using releaser As New ESRI.ArcGIS.ADF.ComReleaser                 releaser.ManageLifetime(Calc)                  Calc.in_table = InputTable                 Calc.field = FieldName                 Calc.expression = Expression                 Calc.expression_type = ExpressionType 'VB, PYTHON, or PYTHON_9.3                 Calc.code_block = CodeBlock                 Calc.out_table = Output                  Result = RunTool(Calc, Nothing)                 If Result Is Nothing Then                     System.Windows.Forms.MessageBox.Show("Could not calculate field")                 End If             End Using         Catch ex As Exception             System.Windows.Forms.MessageBox.Show(ex.ToString, "Calculate Field error")         End Try      End Sub  Friend Function RunTool(ByVal Process As ESRI.ArcGIS.Geoprocessor.IGPProcess, ByVal TC As ESRI.ArcGIS.esriSystem.ITrackCancel) As ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult          Dim Result As ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult          Try             System.Windows.Forms.Cursor.Current = Windows.Forms.Cursors.WaitCursor                          Dim GP As New ESRI.ArcGIS.Geoprocessor.Geoprocessor              Result = CType(GP.Execute(Process, Nothing), ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult)             If Result.Status <> ESRI.ArcGIS.esriSystem.esriJobStatus.esriJobSucceeded Then                 If GP.MessageCount > 0 Then                     For Count = 0 To Globals.GP.MessageCount - 1                         Message += GP.GetMessage(Count) & vbNewLine                     Next                     System.Windows.Forms.MessageBox.Show(Message, "GP Failure")                 End If                               Return Nothing             End If             Return Result         Catch ex As Exception             System.Windows.Forms.MessageBox.Show(ex.ToString & vbNewLine & ex.StackTrace, "Run Geoprocessor")             Return Nothing         End Try      End Function
0 Kudos
NathanSykes
Emerging Contributor
Looks like a good possibility.  I'm away from the office for the weekend now, but will try the code next week and hopefully post back some good news.  Thanks.
0 Kudos
NathanSykes
Emerging Contributor
Thanks for that Ken,

I spent all morning trying to figure out how to get what you suggested to work how I wanted it to, but I've finally managed to do it.

I had to put it in a new module and reference that from another module with the inputs, so it works on my shapefile in one go (rather than looping through all the points in the shapefile and using the calculator on each point).

The only things I had to alter was to comment out both references to Message as it was giving me funny errors which I couldn't shift.  I also changed Globals.GP.MessageCount to just GP.MessageCount as it didn't like the Globals part.

Great help and valuable tip for future work.

Nathan.
0 Kudos
KenBuja
MVP Esteemed Contributor
Glad to hear it worked and that you caught that extra "Globals." It was a remnant of the original code, which I modified for this example. I just didn't modify it well enough...
0 Kudos
RichardFairhurst
MVP Alum
This post was just what I needed to make an Linear Referencing line event split routine refresh the events on screen.  Thanks for posting this code and the response listing the minor corrections required to make it run without errors.
0 Kudos