11

I have a few dozen feature classes, one of which contains the field I am looking for. They are stored in several different file geodatabases.

Is there a quick way of searching each feature class to find the one that has my field? Or do I have to check each one's attribute table in Catalog? Some of the files have the same names but are stored in separate locations.

I would like to be able to do this inside a Calculate Value tool in ModelBuilder, so that each time I needed to, I could run the model on a single file gdb and it would search through all the feature classes within that gdb and look for the field.

So far, I have a feature class iterator which iterates over all the feature classes in the file gdb recursively. Inside the Calculate Value I have the following code:

findField(r"%Feature%", "%Search Field%")

def findField(fc, fi):
  lst = arcpy.ListFields(fc)
  for f in lst:
    if f.name == fi:
      return fc
    else:
      return "not found"

The returned values are collected in Output Values as strings. The output for all the feature classes has been "not found", even though the field exists in at least 4 of them. enter image description here

0

6 Answers 6

20

Check out this function from by Bjorn Kuiper to test if a field exists :

def FieldExist(featureclass, fieldname):
    fieldList = arcpy.ListFields(featureclass, fieldname)

    fieldCount = len(fieldList)

    if (fieldCount == 1):
        return True
    else:
        return False

with the following example of use:

    if (not FieldExist(myFeatureClass, "myField")):
      arcpy.AddError("Field 'myField' does not exist in " + myFeatureClass)
      sys.exit()
0
12

You can use ArcPy:

import arcpy

myField = "test"

env.workspace = "D:/test/data.gdb"
fcs = arcpy.ListFeatureClasses()

for f in fcs:
    fieldList = arcpy.ListFields(f)
    for field in fieldList:   
         if field.name == myField:
             print f

Beside this you can use os.walk for files in your drive as:

path = r"C:"
for root, dirs, files in os.walk(path):
    for fileName in files:
            .........
1
  • I have tried with the updated code, it runs but no output even though the field is in several feature classes within the geodatabase. Commented Jun 8, 2012 at 5:21
11

I would prefer a list comprehension instead of string operations (like accepted answer). In my opinion, this is more readable and pythonic. Furthermore, the list comprehension approach could be extended by adding further functionality (str.lower(), like @RyanDalton did) very easy.

def findField(fc, fi):
  fieldnames = [field.name for field in arcpy.ListFields(fc)]
  if fi in fieldnames:
    return "found in " +fc
  else:
    return "not found in " +fc

If you prefer the one liner if-else Statement:

def findField(fc, fi):
  fieldnames = [field.name for field in arcpy.ListFields(fc)]
  return "found in " + fc if fi in fieldnames else "not found in " + fc

Or even Shorter, but less readable:

    def findField(fc, fi):
      return "found in " + fc if fi in [field.name for field in arcpy.ListFields(fc)] else "not found in " + fc
0
4

If your featureclasses are in Feature Datasets, then @Aragon's solution will not work because you need to walk through the feature datasets and then check the featureclasses.

Using @Aragon's code as well as @gotchula's code from List all feature classes in GDB, including within feature datasets, I produced the following code that will read through all feature datasets and feature classes in a geodatabase.

NOTE: By default ListFields appears to be case-sensitive. I have added code to convert both the user-defined fieldname and the ListField name to lowercase for case-insensitive searches. You probably would also want to disable most of the print statements, but I left them in there so you can follow the code as it is running. I also created the sub-function FindField within the so that I could call it multiple times in the script without having to re-code it.

import arcpy

def FindField(fc,myField):
    fieldList = arcpy.ListFields(fc)
    for field in fieldList:
        if str.lower(str(field.name)) == str.lower(myField):
            print "    " + fc + " contains fieldname: " + myField

myField = "test"
arcpy.env.workspace = "D:/test/data.gdb"

#Search root level featureclasses
for fc in arcpy.ListFeatureClasses():
    print "Searching root level Featureclasses..."
    print "  Searching " + fc
    FindField(fc,myField)

#Search Feature Datasets
for fds in arcpy.ListDatasets('','feature'):
    print "Searching FeatureDataset: " + fds

    for fc in arcpy.ListFeatureClasses('','',fds):
        print "  Searching Featureclass... " + fc
        FindField(fc,myField)
0
3

A few have danced around the way I would do this, but I just want to add an easy one-line way to do this:

if 'fieldname' in [f.name for f in arcpy.ListFields(fc)]:
    ## do something.

What maybe be more useful (if you are iterating through many feature classes) I would use the opposite of the above as a filter:

for fc in arcpy.ListFeatureClasses():
    if not 'fieldname' in [f.name for f in arcpy.ListFields(fc)]:
        continue
    ## now do something with the feature class.
0
1

Found the answer with some help from the code in the answer to Using ListFields and CalculateField to find max value in variable number of fields to populate another field?. I took all the field names, converted them to a string and then searched the string for my field. The code in the Calculate Value now looks as follows:

def findField(fc, fi):
  fieldList = arcpy.ListFields(fc)
  nameList = []
  for f in fieldList:
    nameList.append(f.name)
  str_lst = "!" + "!, !".join(nameList) + "!"
  return "found in" +fc if str_lst.find(fi) > 0 else "not found in " +fc

The Output Values now contains the full list of feature classes which has the field I searched for, and not found for the rest.

Collect Values output

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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