2

I'm trying to create a script tool to use in ModelBuilder that will check the incoming dataset for the existence of a particular field. If the field exists it should simply go on to the next calculate field tool which will use that field, however if the field doesn't exist it should create it before running the next calculate field tool so that I don't get an error from the Calculate field tool, because the field it's trying to use doesn't exist.

I added this script to the ModelBuilder, but it keeps giving me the same error as when I try to run the model and the field doesn't exist. So the script tool is apparently not doing its desired job. Can anyone see an issue with my code? Is there a better way of trying to do this

ModelBuilder

# Import modules
import arcpy
import sys
import traceback

    # Set local variables
    indata = arcpy.GetParameterAsText(0)
    fieldName = "PrintKey_GIS"

    try:
       # check if the PrintKey field exists
       if arcpy.ListFields(indata, fieldName): #if field exists, evaluates to true
           arcpy.AddMessage("PrintKey_GIS field exists") 

       else:
           # Add a new field of that name   
           arcpy.AddField_management(indata, fieldName, "TEXT", "", "",25, "PrintKey_GIS" , "NULLABLE", "", "",)
           arcpy.AddMessage("PrintKey_GIS field does not exist") 

    except Exception as e:
        arcpy.AddMessage(arcpy.GetMessages())
  • I think you are getting the error in model builder because the model can't validate that the field exists at the point the 'calculate field' runs. Instead of using a script tool, just use the 'add field' tool. It doesn't matter if the field already exists. 'add field' will give you a warning, but it should still run OK and the model will be able to validate the 'calculate field' tool because it now knows that the field will exist at that point. See details in my answer, below. – Son of a Beach Aug 21 '18 at 1:54
2

The Check Is Not Actually Required If You are Going to Create The Field Anyhow

If you are going to create the field if it doesn't exist, you don't even need to check for its existence. If the field already exists, and you run arcpy.AddField_management() for that same field, it will do nothing.

Similarly in ModelBuilder if you run the 'Add Field' tool, it will output a message warning that the field already exists, but it will continue on to the next step in the model just fine. (NB: If you do it with a different data type, it will fail, but so long as you use the same data type, it is fine.) Subsequent tools in the model that depend on that field should then be able to validate successfully, because the model can determine that the field will actually exist. Creating the field with a script tool will not allow the model to validate the existence of that field. So with your script tool method the model may be able to run successfully if you run it directly (ie, not in edit mode) but it won't be able to validate and run in edit mode.

I can't see this behaviour of the 'Add Field' tool and arcpy.AddField_management() function documented anywhere, but I noticed it a while back and have found it to be useful.

Of course you would need to be confident that if the field already exists, that it will be of the correct data type, length, etc.

To confirm, I just ran the following code:

print "Adding new field first time"
arcpy.AddField_management(fc, "NewField", "TEXT")
print "Adding new field second time"
arcpy.AddField_management(fc, "NewField", "TEXT")
print "Adding new field third time"
arcpy.AddField_management(fc, "NewField", "TEXT")

and got the following output:

Adding new field first time
Adding new field second time
Adding new field third time

The new field was added to the fc feature class and no errors were reported.

I then ran a model in ModelBuilder that adds a field that already exists and then does a Calculate Field on that same field and it worked fine. I got the output:

Executing (Add Field): AddField C:\Users\<username>\Documents\ArcGIS\Default.gdb\fc NewField TEXT # # # # NULLABLE NON_REQUIRED #
Start Time: Tue Aug 21 11:01:38 2018
WARNING 000012: NewField already exists
Succeeded at Tue Aug 21 11:01:38 2018 (Elapsed Time: 0.08 seconds)
Executing (Calculate Field): CalculateField C:\Users\<username>\Documents\ArcGIS\Default.gdb\fc NewField 'blah' PYTHON #
Start Time: Tue Aug 21 11:01:38 2018
Succeeded at Tue Aug 21 11:01:38 2018 (Elapsed Time: 0.12 seconds)

It's up to you whether you want to be extra safe and do the check anyhow, but at least in version 10.3.1 and 10.5.1 that I've used recently, it works fine this way. It's quite convenient behaviour (at least for this kind of scenario).

If a Field Existence Check Really Is Required

There are some situations when you really do need to check for the existence of a field (eg, you don't want to create a new field, but you do want to do something different depending on if the field exists or not). In this case, I use something like:

if len(arcpy.ListFields(fc, fieldName)):
    #  Field exists.  Do something.
else:
    #  Field does not exist.  Do something else.
0

It seems you needed to check a list of fields in each fc. so here it is my attempt. you can utilise in model builder or Just run standalone. Don't forget to add addField's required field type, field length etc as per your convenience.

import arcpy
import os

arcpy.env.workspace = r"C:\Users\Sanjay\Documents\ArcGIS\SimilarPoints by attribute in polygon\mygdb.gdb" #Parameter1

def FieldExist(featureclass, fieldname):                   #* Start if function to check if field exist  */
    fieldList = arcpy.ListFields(featureclass, fieldname)

    fieldCount = len(fieldList)

    if (fieldCount == 1):
        return True
    else:
        return False                                    #* End of function to check if field exist  */

datasets = arcpy.ListDatasets(feature_type='feature')
datasets = [''] + datasets if datasets is not None else []

ListOfFieldNeeded = ["ID","Creator","checker","Approver"]#parameter2  #List of field to check if not exist add it.
for Afield in ListOfFieldNeeded:                           #will check each fc in gdb and add field
    for ds in datasets:
        for fc in arcpy.ListFeatureClasses(feature_dataset=ds):
            if not FieldExist(fc,Afield):
                #print "{} Not Exist in featureclass {}".format(Afield,fc)
                arcpy.AddField_management(fc,Afield,"TEXT")
                print "Field {} added in fc {}".format(Afield,fc)   #Addmessage to print model builder environment
                #you can add your script validation using else or exception occures
  • Just curious... what is the purpose of prepending an empty string to the datasets list, where you have datasets = [''] + datasets ... ? – Son of a Beach Aug 21 '18 at 0:52
  • Check last comment of first answer here. gis.stackexchange.com/questions/5893/… – GIS Data Butcher Aug 21 '18 at 5:07
  • Thanks... to get the top-level feature classes as well as the feature classes from within feature datasets, all within the one loop. Makes sense. – Son of a Beach Aug 21 '18 at 5:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.