2

I need to automatically optimize text field character length to their current largest attribute character count. For example the field "MyName" is 250 characters long, but has attributes that are a maximum 6 characters long, the field "MyName" character length needs to updated from 250 characters to 6 characters.

I can do this processes manually (with possible errors), but I need a faster more reliable method to give to ArcGIS users. Before I start to write an ArcPy tool, has anymore written something like this before?

I'm guessing the ArcPy method would loop through each text field (A) and then loop through each row and note the largest attribute length (B), then it would pass the field name (A) and character length (B) to the output.

  • What benefit do you expect from this activity? It's not possible on fixed-width storage types (shapefiles), and doesn't change the storage in any way on file or enterprise geodatabase (except that you would get an error if a row with longer content were added). – Vince Jan 21 '16 at 3:29
  • A core system exports feature classes with the maximum allowed text field characters. The users dislike the look of this in the attribute table. In addition MapInfo has limited functionality caused by bloated character length's in these feature class (they cannot be made into editable tabs). I realize that the original feature class fields cannot be "updated" therefore I'm aiming for an "updated" output. – GISI Jan 21 '16 at 3:40
  • How many fields and how many records? – Midavalo Jan 21 '16 at 4:17
4

The basics:

  1. Determine which of your fields are text fields.
  2. Iterate values in those fields with a cursor and store the longest lengths in a dictionary.
  3. Create a fieldmappings object and populate it with all your fields. If it's a text field, update its output field's length with the appropriate value.
  4. Perform a feature class to feature class, using the fieldmappings object.

Something like this:

#input feature class
inFc = r"C:\Users\e1b8\Desktop\E1B8\Workspace\temp.gdb\AOI_18_Leaks_Snapped"

#import modules
print "importing"
import arcpy
import os

#determine text fields
print "determing string fields"
textFields = [field.name for field in arcpy.ListFields (inFc) if field.type == "String"]

#create empty dictionary to store fields and lengths
countDi = {}

#iterate rows with cursor
print "determing field lengths"
with arcpy.da.SearchCursor (inFc, textFields) as cursor:
    for row in cursor:
        #iterate length of text fields list
        for i in range (len (textFields)):
            #skip nulls
            if not row [i]:
                continue
            #check if key (field name) is in dictionary
            if not textFields [i] in countDi:
                #if not, add to dictionary
                countDi [textFields [i]] = len (row [i])
            #if so, check if length for row value is greater than dict value
            elif len (row [i]) > countDi [textFields [i]]:
                #if so, update value
                countDi [textFields [i]] = len (row [i])
del cursor

#update null fields with length of 1 (optional)
print "checking for all-null fields"
for field in textFields:
    if not field in countDi:
        countDi [field] = 1

#create fieldmappings object
print "creating and updating fieldmappings object"
fms = arcpy.FieldMappings ()
#iterate all fields in feature class
for field in arcpy.ListFields (inFc):
    #skip OID and geometry fields
    if field.type in ["Geometry", "OID"]:
        continue
    #create field map object
    fm = arcpy.FieldMap ()
    #get field name
    fieldName = field.name
    #add field to field map
    fm.addInputField (inFc, fieldName)
    #update length if field is in field count dictionary
    if fieldName in countDi:
        #update field length with value from dictionary
        field.length = countDi [fieldName]
        #update output field
        fm.outputField = field
    #add fieldmap to fieldmappings
    fms.addFieldMap (fm)

#output feature class name
outPath, inName = os.path.split (inFc)
outName = inName + "_UpdateFields"
i = 0
outFc = os.path.join (outPath, outName)
#create unique file name
while arcpy.Exists (outFc):
    i += 1
    outFc = os.path.join (outPath, outName + "_" + str (i))
outName = os.path.basename (outFc)

#export
print "exporting"
arcpy.FeatureClassToFeatureClass_conversion (inFc, outPath, outName, field_mapping = fms)

print "created:"
print outFc

print
print "done"
  • 1
    I tested this ArcPy script at 10.3.1 and it works perfectly. I will wrap it in a script tool and make it available to our users. – GISI Jan 21 '16 at 5:12

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.