Select to view content in your preferred language

Python: Calculate Area

6391
11
11-03-2010 07:27 AM
LornaMurison
Regular Contributor
Hi everyone,
Here is my daily python question just to keep you all on your toes...

I would like to add a field called "LCArea" and calculate, you guessed it, the area.
But I don't know what to put in the codeblock because I can only find area calculation codes in VBA.
I would appreciate some guidance as to how to use the expression and codeblock parameters.
Thanks.


And as a side note, when using the Advanced Field Calculator in ArcMap, it defaults to VBA.  How do I do field calculations using python in ArcMap?

Thanks!



# If the output is a geodatabase feature class...
if outType == "FeatureClass":
    # Then export the attribute table
    gp.MakeTableView_management(dissolveOutputFC, tableView, "", "", "UCID Catchment VISIBLE; GRIDCODE LandCov VISIBLE; Shape_Area LCArea VISIBLE")
    gp.TableToDbase_conversion (tableView, tableFolder)
# If the output is a shapefile...
elif outType == "ShapeFile":
    # Then add and calculate an area field...
    gp.MakeTableView_management(dissolveOutputFC, tableView, "", "", "UCID Catchment VISIBLE; GRIDCODE LandCov VISIBLE")
    gp.AddField_management (tableView, "LCArea", "DOUBLE", "", "", "", "", "", "", "")
    expression =
    codeblock = 
    gp.CalculateField_management (tableView, "LCArea", expression, "PYTHON_9.3", codeblock)
    gp.TableToDbase_conversion (tableView, tableFolder)
    # And export the attribute table
#else:
    # Error handler to exit the script and return some message
#print 'done'
0 Kudos
11 Replies
ChrisSnyder
Honored Contributor
There's a bunch of ways to do this, but I've found that the (new in v9.3) ESRI "unit keywords" are the easiest. For example (see the @ACRES part):

gp.AddField_management(edgeDissolveFC, "ACRES", "DOUBLE", "", "", ""); showGpMessage()
gp.CalculateField_management(edgeDissolveFC, "ACRES", "!SHAPE.AREA@ACRES!", "PYTHON", ""); showGpMessage()


For a list of all the keywords: http://webhelp.esri.com/arcgisdesktop/9.3/index.cfm?id=1812&pid=1808&topicname=Calculate_Field_(Data...)

Some advice on using complex expressions in the codeblock thing: Don't do it! Instead, use an updatecursor. The syntax is MUCH easier, especially for complicated things. For example: http://forums.esri.com/Thread.asp?c=93&f=1729&t=262236#806786

Per your last question: Use the CalculateField tool in the Toolbox. The "right-click calculate field tool" in the table GUI does not have the "PYTHON" option (at least in v9.3 it didn't.
0 Kudos
DanPatterson_Retired
MVP Emeritus
Version 10 does allow for the use of Python
0 Kudos
DaleHoneycutt
Deactivated User
0 Kudos
LornaMurison
Regular Contributor
Thank-you,
Shape.Area worked while I was running the code in pythonwin.  I have now imported the code into a toolbox and it is no longer working.
In the code below, if tempWorkspace is a geodatabase the code works, if it's a file, then I get an error saying field "LCArea" does not exist within table.


Import Modules
import arcgisscripting
# Create Geoprocessor object
gp = arcgisscripting.create(9.3)
gp.overwriteoutput = True
# Set up parameters
catchmentsFC = gp.GetParameterAsText(0) #in a toolbox GUI, Type = FeatureLayer
landCoverFC = gp.GetParameterAsText(1) #in a toolbox GUI, Type = FeatureLayer
tempWorkspace = gp.GetParameterAsText (2) #in a toolbox GUI, Type = Workspace
tableFolder = gp.GetParameterAsText (3) #in a toolbox GUI, Type = Folder
tableName = gp.GetParameterAsText (4) #in a toolbox GUI, Type = String
tableView = tableFolder + "\\" + tableName
gp.Workspace = tempWorkspace
wsDesc = gp.Describe(tempWorkspace)
wsType = wsDesc.WorkspaceType
if wsType == "FileSystem":
    # Intersect land cover and catchments
    gp.Intersect_Analysis (catchmentsFC + ";" + landCoverFC, "Intersect.shp", "ALL", "", "INPUT")
    # Dissolve output based on catchment and land cover IDs
    gp.Dissolve_management ("Intersect.shp", "Dissolve.shp", "UCID; GRIDCODE", "", "MULTI_PART", "")
    # Create a table, add and caculate the area
    gp.MakeTableView_management("Dissolve.shp", tableView, "", "", "UCID Catchment VISIBLE; GRIDCODE LandCov VISIBLE")
    gp.AddField_management (tableView, "LCArea", "DOUBLE", "", "", "", "", "", "", "")
    expression = "!SHAPE.AREA@SQUAREMETERS!"
    fields = gp.ListFields (tableView)
    gp.CalculateField_management (tableView, "LCArea", expression, "PYTHON_9.3", "")
    # Export the table to dBASE
    gp.TableToDbase_conversion (tableView, tableFolder)    
elif wsType == "LocalDatabase":
    gp.Intersect_Analysis (catchmentsFC + ";" + landCoverFC, "Intersect", "ALL", "", "INPUT")
    # Dissolve output based on catchment and land cover IDs
    gp.Dissolve_management ("Intersect", "Dissolve", "UCID; GRIDCODE", "", "MULTI_PART", "")
    #desc = gp.Describe("Dissolve")
    gp.MakeTableView_management("Dissolve", tableView, "", "", "UCID Catchment VISIBLE; GRIDCODE LandCov VISIBLE; Shape_Area LCArea VISIBLE")
    gp.TableToDbase_conversion (tableView, tableFolder)
print 'done'
0 Kudos
LornaMurison
Regular Contributor
Well,
I threw the whole add and calculate field part into a try/except block and it works now.  I didn't actually change any of the code.
I'm happy that it works, but does anyone know why that would solve the problem?


if wsType == "FileSystem":
    # Intersect land cover and catchments
    gp.Intersect_Analysis (catchmentsFC + ";" + landCoverFC, "Intersect.shp", "ALL", "", "INPUT")
    # Dissolve output based on catchment and land cover IDs
    gp.Dissolve_management ("Intersect.shp", "Dissolve.shp", "UCID; GRIDCODE", "", "MULTI_PART", "")
    # Create a table, add and caculate the area
    gp.MakeTableView_management("Dissolve.shp", tableView, "", "", "UCID Catchment VISIBLE; GRIDCODE LandCov VISIBLE")
    LCArea = "LCArea"
    try:
        gp.AddField_management (tableView, LCArea, "DOUBLE", "", "", "", "", "", "", "")    
        expression = "!SHAPE.AREA@SQUAREMETERS!"
        fields = gp.ListFields (tableView)
        gp.CalculateField_management (tableView, LCArea, expression, "PYTHON_9.3", "")
    except:
        gp.GetMessages()
    # Export the table to dBASE
    gp.TableToDbase_conversion (tableView, tableFolder)
0 Kudos
LornaMurison
Regular Contributor
As it turns out, it didn't solve the problem.  The field "LCArea" is added, but it is not calculated, it remains filled with zeroes.
No messages are returned... at least not in the toolbox.  I don't really know where gp.GetMessages() is supposed to send its messages though...
0 Kudos
DanPatterson_Retired
MVP Emeritus
if it adds the field, what is the precision and scale?, have you tried to specify those parameters explicitly to ensure that any calculation will fit?
0 Kudos
LornaMurison
Regular Contributor
If I don't specify anything, the field that adds has a precision and scale of 0.
I tried specifying 10 and 9 and the resulting field had a precision of 18 and a scale of 9, still filled with zeroes.
0 Kudos
LoganPugh
Frequent Contributor
When you put the try/except in, it didn't prevent the error from occuring, just hid it from you. Either remove the try/except or tweak the except part to make the error message visible (calling gp.getmessages() by itself just gobbles up the message without displaying it anywhere):

except:
    gp.AddError(gp.GetMessages())
0 Kudos