Wow, I haven't looked at this thread in a long time. I see the code samples I posted have been downloaded many times. I wrote that a long time ago and have updated it way too many times since...In case anyone is interested, here is the code for my latest version which should handle both 10.0 and 10.x versions of ArcGIS:
import arcpy, os, sys
# test version for cursor type (data access module available @ 10.1 +)
ver = arcpy.GetInstallInfo()['Version']
dataAccess = False
if ver != '10.0':
dataAccess = True
def Message(msg):
print str(msg)
arcpy.AddMessage(str(msg))
return
def create_field_name(fc, new_field):
'''Return a valid field name that does not exist in fc and
that is based on new_field.
fc: feature class, feature layer, table, or table view
new_field: new field name, will be altered if field already exists
Example:
>>> fc = 'c:\\testing.gdb\\ne_110m_admin_0_countries'
>>> createFieldName(fc, 'NEWCOL') # NEWCOL
>>> createFieldName(fc, 'Shape') # Shape_1
'''
# if fc is a table view or a feature layer, some fields may be hidden;
# grab the data source to make sure all columns are examined
fc = arcpy.Describe(fc).catalogPath
new_field = arcpy.ValidateFieldName(new_field, fc)
# maximum length of the new field name
maxlen = 64
dtype = arcpy.Describe(fc).dataType
if dtype.lower() in ('dbasetable', 'shapefile'):
maxlen = 10
# field list
fields = [f.name.lower() for f in arcpy.ListFields(fc)]
# see if field already exists
if new_field.lower() in fields:
count = 1
while new_field.lower() in fields:
if count > 1000:
raise bmiError('Maximum number of iterations reached in uniqueFieldName.')
if len(new_field) > maxlen:
ind = maxlen - (1 + len(str(count)))
new_field = '{0}_{1}'.format(new_field[:ind], count)
count += 1
else:
new_field = '{0}_{1}'.format(new_field, count)
count += 1
return new_field
def AttributeUpdate(source_table, in_field, update_fields, join_table, join_key, join_values):
# Check input parameters
if not arcpy.Exists(source_table):
print '"%s" not found!\nPlease verify that full path of table exists' %source_table
sys.exit()
if not arcpy.Exists(join_table):
print '"%s" not found!\nPlease verify that full path of table exists' %join_table
sys.exit()
if in_field not in [f.name for f in arcpy.ListFields(source_table)]:
print "'%s' not found in \"%s\"" %(in_field,os.path.basename(source_table))
sys.exit()
if join_key not in [f.name for f in arcpy.ListFields(join_table)]:
print "'%s' not found in \"%s\"" %(join_key,os.path.basename(join_table))
sys.exit()
for fld in update_fields:
if fld not in [f.name for f in arcpy.ListFields(source_table)]:
print "'%s' not found in \"%s\"" %(fld,os.path.basename(source_table))
print 'Please verify that field names match in "%s"' %os.path.basename(source_table)
sys.exit()
for fldb in join_values:
if fldb not in [f.name for f in arcpy.ListFields(join_table)]:
print "'%s' not found in \"%s\"" %(fldb,os.path.basename(join_table))
print 'Please verify that field names match in "%s"' %os.path.basename(join_table)
sys.exit()
if not isinstance(update_fields, list):
update_fields = list(update_fields)
if not isinstance(join_values, list):
join_values = list(join_values)
# Make sure there is matching number of join and update fields
if len(update_fields) == len(join_values):
up_flds_list = [f for f in arcpy.ListFields(source_table) if f.name in update_fields]
up_flds_dict = dict([(f.name,f.type) for f in up_flds_list])
jn_flds_list = [f for f in arcpy.ListFields(join_table) if f.name in join_values]
jn_flds_dict = dict([(f.name,f.type) for f in jn_flds_list])
types_dict = {'String': str, 'Single':float, 'Double':float, 'Integer':long, 'SmallInteger':int}
path_dict = {}
if dataAccess:
# Create Dictionary
join_values.insert(0, join_key)
with arcpy.da.SearchCursor(join_table, join_values) as srows:
for srow in srows:
path_dict[srow[0]] = tuple(srow for i in range(len(join_values[1:])))
# Update Cursor
update_index = list(range(len(update_fields)))
row_index = list(x+1 for x in update_index)
update_fields.insert(0, in_field)
with arcpy.da.UpdateCursor(source_table, update_fields) as urows:
for row in urows:
if row[0] in path_dict:
allVals =[path_dict[row[0]] for i in update_index]
for r,v in zip(row_index, allVals):
row = v
urows.updateRow(row)
print 'Fields in "%s" updated successfully' %(os.path.basename(source_table))
else:
# version 10.0
srows = arcpy.SearchCursor(join_table)
for row in srows:
path_dict[row.getValue(join_key)] = tuple(row.getValue(i) for i in join_values)
del srows
# Update Cursor
rows = arcpy.UpdateCursor(source_table)
for row in rows:
theVal = row.getValue(in_field)
if theVal in path_dict:
for i in range(len(update_fields)):
try:
theType = types_dict[jn_flds_dict[join_fields]]
row.setValue(update_fields,theType(path_dict[theVal]))
except:
row.setValue(update_fields, path_dict[theVal])
rows.updateRow(row)
del rows
else:
print 'ERROR: Number of update fields and value fields does not match'
return
def CopyFields(source_table, in_field, join_table, join_key, join_values=[]):
'''
Copies field(s) from one table to another
source_table: table in which to add new fields
in_field: a field that has common values to a field in the join_table.
think of this as a "join_field"
join_table: table with fields to add to source_table
join_key: field to match values of the "in_field"
join_values: fields to add to source_table (list)
'''
# Get Catalog path (for feature layers and table views)
cat_path = arcpy.Describe(source_table).catalogPath
# Find out if source table is NULLABLE
if not os.path.splitext(cat_path)[1] in ['.dbf','.shp']:
nullable = 'NULLABLE'
else:
nullable = 'NON_NULLABLE'
# Add fields to be copied
update_fields = []
join_list = arcpy.ListFields(join_table)
for field in join_list:
ftype = field.type
name = field.name
length = field.length
pres = field.precision
scale = field.scale
alias = field.aliasName
domain = field.domain
for fldb in join_values:
if fldb == name:
name = create_field_name(source_table, fldb)
arcpy.AddField_management(source_table,name,ftype,pres,scale,length,alias,nullable,'',domain)
Message("Added '%s' field to \"%s\"" %(name, os.path.basename(source_table)))
update_fields.insert(join_values.index(fldb), name.encode('utf-8'))
# update new fields
path_dict = {}
if dataAccess:
# Create Dictionary
join_values.insert(0, join_key)
with arcpy.da.SearchCursor(join_table, join_values) as srows:
for srow in srows:
path_dict[srow[0]] = tuple(srow for i in range(1,len(join_values)))
# Update Cursor
update_index = list(range(len(update_fields)))
row_index = list(x+1 for x in update_index)
update_fields.insert(0, in_field)
with arcpy.da.UpdateCursor(source_table, update_fields) as urows:
for row in urows:
if row[0] in path_dict:
try:
allVals =[path_dict[row[0]] for i in update_index]
for r,v in zip(row_index, allVals):
row = v
urows.updateRow(row)
except: pass
else:
# version 10.0
rows = arcpy.SearchCursor(join_table)
for row in rows:
path_dict[row.getValue(join_key)] = tuple(row.getValue(join_values) for i in range(len(join_values)))
del rows
# Update Cursor
rows = arcpy.UpdateCursor(source_table)
for row in rows:
theVal = row.getValue(in_field)
if theVal in path_dict:
try:
for i in range(len(update_fields)):
row.setValue(update_fields,path_dict[theVal])
rows.updateRow(row)
except: pass
del rows
Message('Fields in "%s" updated successfully' %(os.path.basename(source_table)))
return
if __name__ == '__main__':
source = r'C:\TEMP\PermitTest\test.gdb\Permits'
join = r'C:\TEMP\PermitTest\test.gdb\orono_test'
fields = ['BLDG_NUM', 'SALE_DATE', 'APPLICANT']
# Run it
CopyFields(source, 'PID_NO', join, 'PID_NO', fields)
Also, I will be at the Esri UC this year so I'll take you up on that cold drink!