Hey all,
I'm using field values as input for naming exported attachments, and I'm running into an issue with domains.
Namely, if the field uses a coded value domain, it will grab the code and not the value.
How can I grab the value?
I found this post here but I'm not sure how to put it together; I was able to create the initial dictionary of codes and values, but I'm not sure how to connect that to my fields afterwards.
The code runs as :
I have steps 1,2, and 4, but I can't figure out how to make step 3 work.
Code sample
'''Rough order of how I think it should go?
Step 1 is definitely supposed to be at the bottom'''
'''Step 4''' # Mostly lifted directly from that example I link
testDom = arcpy.ListFields(inFC)
for field in testDom:
if field.domain != "": #I only care about domains if there is one. Also need to specify that it's a coded value domain somehow.
cvdTable = arcpy.DomainToTable_management(myGDB, field.domain, 'in_memory/cvdTable', 'codeField', 'descriptionField')
d = {} #Create an empty dictionary.
rows = arcpy.SearchCursor(cvdTable) #Create a cursor to loop through the table holding the domain and code info
for row in rows: # Loop through each row in the table.
d[row.codeField] = row.descriptionField # For each row in the table populate the key with the code field and the value from the description field
'''Step 2'''
primeNames = dict()
with arcpy.da.SearchCursor(FeatureClass, [relPairO, nameField1]) as cursor:
for row in cursor:
primeNames[row[0]] = row[1] #Every time you check this dictionary for the relation key, it will direct you to the right entry in the primary naming field.
'''Step 1'''
with arcpy.da.SearchCursor(inTable,['DATA', 'ATT_NAME', 'ATTACHMENTID', relPairA]) as cursor:
for row in cursor:
relPairKey = row[3]
fieldValue = primeNames[relPairKey] # Value of specified field in feature class
Also, this is a total beginner question, but in the example that I linked, what happens to that domain table? Is it automatically deleted?
Thanks!
Solved! Go to Solution.
I ended up making a table from the domain, then joining to the original FC.
Below is my code sample, with the addition of lines #6-13, which validate that the domain is a Code Value Domain (checked in line #16).
This validation is necessary; if you use a Range domain with this workflow otherwise, it will return "Min Value", "Max Value", or nothing.
I have a little more stuff to do on this project, but the end is very near.
Thanks everyone!
def grabDomain (workspace, inFC, namefield, relPairO):
'''Grabs the Coded Value of a coded Value Domain'''
''' Otherwise just grabs the field's value'''
names = dict()
rawDomain = arcpy.da.ListDomains(workspace) #list of all domains in the GDB
valDomain = [] #list of valid domains
for dom in rawDomain:
if dom.domainType != "Range": #add Coded Value Domains to the valid list
valDomain.append(dom.name)
listFlds = arcpy.ListFields(inFC, namefield)
for field in listFlds:
if (field.domain != "") and (field.domain in valDomain): #For retreiving Coded values
#Create an in-memory table representing the domain.
codeTable = arcpy.DomainToTable_management(workspace, field.domain, 'in_memory/codeTable', "codeField", "descriptionField")
inFC2 = arcpy.management.AddJoin(inFC, namefield, codeTable, "codeField") # Join said table to your Feature Class.
# Okay this next part is kinda tricky
# perform your search cursor on the joined feature class, but use the ORIGINAL FC to find the field names.
with arcpy.da.SearchCursor(inFC2, [f"{inFC}.{relPairO}", f"{inFC}.{namefield}", f"codeTable.descriptionField"]) as cursor:
for row in cursor:
names[row[0]] = row[2]
else: #Otherwise just grabs the code
with arcpy.da.SearchCursor(inFC, [relPairO, namefield]) as cursor:
for row in cursor:
names[row[0]] = row[1] #Every time you check this dictionary for the relation key, it will direct you to the right entry in the primary naming field.
return names
Looks like you are creating the code:value dictionary in the first cursor, but since its scope is under the for loop, it is destroyed when the loop finishes. Move the d = {} above the for loop so it persists and can be used in other parts of your code.
To get the code value, it would be a simple g.get('code (key) here', <default value here if you want it to return a value when the code is not in the keys>)
For your second question, since the table is created in the 'memory' workspace, it is sent to the digital abyss when there is no more reference/ need for it and garbage collector does its thing. Or when the script ends and python releases the memory.
Good to know, thanks!
I ended up making a table from the domain, then joining to the original FC.
Below is my code sample, with the addition of lines #6-13, which validate that the domain is a Code Value Domain (checked in line #16).
This validation is necessary; if you use a Range domain with this workflow otherwise, it will return "Min Value", "Max Value", or nothing.
I have a little more stuff to do on this project, but the end is very near.
Thanks everyone!
def grabDomain (workspace, inFC, namefield, relPairO):
'''Grabs the Coded Value of a coded Value Domain'''
''' Otherwise just grabs the field's value'''
names = dict()
rawDomain = arcpy.da.ListDomains(workspace) #list of all domains in the GDB
valDomain = [] #list of valid domains
for dom in rawDomain:
if dom.domainType != "Range": #add Coded Value Domains to the valid list
valDomain.append(dom.name)
listFlds = arcpy.ListFields(inFC, namefield)
for field in listFlds:
if (field.domain != "") and (field.domain in valDomain): #For retreiving Coded values
#Create an in-memory table representing the domain.
codeTable = arcpy.DomainToTable_management(workspace, field.domain, 'in_memory/codeTable', "codeField", "descriptionField")
inFC2 = arcpy.management.AddJoin(inFC, namefield, codeTable, "codeField") # Join said table to your Feature Class.
# Okay this next part is kinda tricky
# perform your search cursor on the joined feature class, but use the ORIGINAL FC to find the field names.
with arcpy.da.SearchCursor(inFC2, [f"{inFC}.{relPairO}", f"{inFC}.{namefield}", f"codeTable.descriptionField"]) as cursor:
for row in cursor:
names[row[0]] = row[2]
else: #Otherwise just grabs the code
with arcpy.da.SearchCursor(inFC, [relPairO, namefield]) as cursor:
for row in cursor:
names[row[0]] = row[1] #Every time you check this dictionary for the relation key, it will direct you to the right entry in the primary naming field.
return names