import arcpy from arcpy import env # Define workspace env.workspace = "C:/PythonParcelProcesses" # paths to tables masterTable = 'UpdateInsertTo.dbf' subsetTable = 'UpdateInsertFrom.dbf' # define fields: keyField = 'APN' testFields = ['APN_SUFFIX', 'TRA', 'NAME_1', 'NAME_2', 'MAIL_ADDR', 'CTY_STA'] # dictionary of the contents of the subset table # APN is key, fields to test are stored in an ordered list subsetDict = {} sC = arcpy.SearchCursor(subsetTable) for row in sC: subsetDict[row.getValue(keyField)] = [row.getValue(field) for field in testFields] del sC, row # get list of values that need to be updated updateDict = {} sC = arcpy.SearchCursor(masterTable) for row in sC: key = row.getValue(keyField) testList = [row.getValue(field) for field in testFields] # try to get record in subsetDict to see if it has changed # if the subset table didn't contain a record for this entry, will trow KeyError (that's fine - do nothing) try: # if records have changed add to updateDict and delete from subsetDict if subsetDict[key] != testList: updateDict[key] = subsetDict[key] del subsetDict[key] # records are the same, delete from subsetDict else: del subsetDict[key] except KeyError: # this APN only exists in the master table, do nothing... pass del sC, row # anything left in subsetDict is new, can use insertCursor iC = arcpy.InsertCursor(masterTable) for key in subsetDict: row = iC.newRow() row.setValue(keyField, key) for i in range(len(testFields)): field = testFields row.setValue(field, subsetDict[key]) iC.insertRow(row) del row del iC # anything in updateDict needs to be updated, use updateCursor uC = arcpy.UpdateCursor(masterTable) for row in uC: key = row.getValue(keyField) if row.getValue(keyField) in updateDict: for i in range(len(testFields)): field = testFields row.setValue(field, updateDict[key]) uC.updateRow(row) del uC, row, updateDict, subsetDict
import arcpy # paths to tables masterTable = '//masterTable' subsetTable = '//subsetTable' # define fields: keyField = 'APN' testFeild1 = 'a' testField2 = 'b' #... and so on ## If you know all your fields and will never need to change them I would recommend using the 'dynamic' noation row.APN inseatd of row.getValue('APN') as I have used below # dictionary of the contents of the subset table # APN is key, fields to test are stroed in an ordered list subsetDict = {} sC = arcpy.SearchCursor(subsetTable) for row in sC: subsetDict[row.getValue(keyField)] = [row.getValue(testField1), row.getValue(testField2)] del sC, row # get list of values that need to be updated updateDict = {} sC = arcpy.SearchCursor(masterTable) for row in sC: key = row.getValue(keyField) testList = [row.getValue(testField1), row.getValue(testField2)] # if records have changed add to updateDuct and delete from subsetDict if subsetDict[key] != testList: updateDict[key] = subsetDict[key] del subsetDict[key] # records are the same, delete from subsetDict else: del subsetDict[key] del sC, row # anything left in subsetDict is new, can use insertCursor iC = arcpy.InsertCursor(masterTable) for key in subsetDict: row = iC.newRow() row.setValue(keyField, key) row.setValue(testField1, subsetDict[key][0]) row.setValue(testField2, subsetDict[key][1]) iC.insertRow(row) del row del iC, subsetDict # anything in updateDuct needs to be updated, use updateCursor uC = arcpy.UpdateCursor(masterTable) for row in uC: if row.getValue(keyField) in updateDict: row.setValue(testField1, updateDict[key][0]) row.setValue(testField2, updateDict[key][1]) del uC, row, updateDict
if subsetDict[key] != testList: updateDict[key] = subsetDict[key] del subsetDict[key] # records are the same, delete from subsetDict else: del subsetDict[key] del sC, row
import arcpy from arcpy import env # Define workspace env.workspace = "C:/PythonParcelProcesses" # paths to tables masterTable = 'UpdateInsertTo.dbf' subsetTable = 'UpdateInsertFrom.dbf' # define fields: keyField = 'APN' testField1 = 'APN_SUFFIX' testField2 = 'TRA' testField3 = 'NAME_1' testField4 = 'NAME_2' testField5 = 'MAIL_ADDR' testField6 = 'CTY_STA' #... and so on ## If you know all your fields and will never need to change them I would recommend using the 'dynamic' notation row.APN instead of row.getValue('APN') as I have used below # dictionary of the contents of the subset table # APN is key, fields to test are stored in an ordered list subsetDict = {} sC = arcpy.SearchCursor(subsetTable) for row in sC: subsetDict[row.getValue(keyField)] = [row.getValue(testField1), row.getValue(testField2), row.getValue(testField3), row.getValue(testField4), row.getValue(testField5), row.getValue(testField6)] del sC, row # get list of values that need to be updated updateDict = {} sC = arcpy.SearchCursor(masterTable) for row in sC: key = row.getValue(keyField) testList = [row.getValue(testField1), row.getValue(testField2), row.getValue(testField3), row.getValue(testField4), row.getValue(testField5), row.getValue(testField6)] # if records have changed add to updateDict and delete from subsetDict if subsetDict[key] != testList: updateDict[key] = subsetDict[key] del subsetDict[key] # records are the same, delete from subsetDict else: del subsetDict[key] del sC, row # anything left in subsetDict is new, can use insertCursor iC = arcpy.InsertCursor(masterTable) for key in subsetDict: row = iC.newRow() row.setValue(keyField, key) row.setValue(testField1, subsetDict[key][0]) row.setValue(testField2, subsetDict[key][1]) row.setValue(testField3, subsetDict[key][2]) row.setValue(testField4, subsetDict[key][3]) row.setValue(testField5, subsetDict[key][4]) row.setValue(testField6, subsetDict[key][5]) iC.insertRow(row) del row del iC, subsetDict # anything in updateDict needs to be updated, use updateCursor uC = arcpy.UpdateCursor(masterTable) for row in uC: if row.getValue(keyField) in updateDict: row.setValue(testField1, updateDict[key][0]) row.setValue(testField2, updateDict[key][1]) row.setValue(testField3, updateDict[key][2]) row.setValue(testField4, updateDict[key][3]) row.setValue(testField5, updateDict[key][4]) row.setValue(testField6, updateDict[key][5]) del uC, row, updateDict
# get list of values that need to be updated updateDict = {} sC = arcpy.SearchCursor(masterTable) for row in sC: key = row.getValue(keyField) testList = [row.getValue(testField1), row.getValue(testField2), row.getValue(testField3), row.getValue(testField4), row.getValue(testField5), row.getValue(testField6)] # try to get record in subsetDict to see if it has changed # if the subset table didn't contain a record for this entry, will trow KeyError (that's fine - do nothing) try: # if records have changed add to updateDict and delete from subsetDict if subsetDict[key] != testList: updateDict[key] = subsetDict[key] del subsetDict[key] # records are the same, delete from subsetDict else: del subsetDict[key] except KeyError: # this APN only exists in the master table, do nothing... pass del sC, row
The master table is now being updated with new rows from the subset table
Strangely the first new row is being placed last in the master table
and a KeyError is being called on its key field value
and, although a print command placed after the last line confirms that the script is completing, the insertCursor block does not seem to be working.
Do you mean: 1. 'the new rows are being added at the end', or 2. ' the top-most new row is bottom-most in the updated table'? Either way:1. The InsertCursor adds a new row to the bottom of the table, so this is expected.2. Dictionary keys are not actually ordered; so the order in which the rows are added to the table is (effectively) random.
I need more detail on this.A KeyError means that it is asking the dictionary for a key that doesn't exist. Which block is this occurring in?
If the Insert Cursor is not working, new rows would not be being added from the subset table (your first comment) - do you mean the Update Cursor?
Mark,can you send me the files you are testing with (you can attach files to posts)? If you have to, zip them together.I just can't figure what the problem might be without being able to test stuff and see it for myself.Stacy
Stacy,I have sent you a private message to arrange to send the data by more secure means. Thanks.Mark
for row in uC: if row.getValue(keyField) in updateDict: row.setValue(testField1, updateDict[key][0]) row.setValue(testField2, updateDict[key][1]) row.setValue(testField3, updateDict[key][2]) row.setValue(testField4, updateDict[key][3]) row.setValue(testField5, updateDict[key][4]) row.setValue(testField6, updateDict[key][5]) uC.updateRow(row)
Hate to barge in on a good conversation, but it looks like you are missing an update in your update cursor. for row in uC: if row.getValue(keyField) in updateDict: row.setValue(testField1, updateDict[key][0]) row.setValue(testField2, updateDict[key][1]) row.setValue(testField3, updateDict[key][2]) row.setValue(testField4, updateDict[key][3]) row.setValue(testField5, updateDict[key][4]) row.setValue(testField6, updateDict[key][5]) uC.updateRow(row)
for row in uC: key = row.getValue(keyField) if row.getValue(keyField) in updateDict: row.setValue(testField1, updateDict[key][0]) row.setValue(testField2, updateDict[key][1]) row.setValue(testField3, updateDict[key][2]) row.setValue(testField4, updateDict[key][3]) row.setValue(testField5, updateDict[key][4]) row.setValue(testField6, updateDict[key][5]) uC.updateRow(row)
I was executing code similar to this. Have you tried declaring the 'key' in the update cursor. Ex:for row in uC: key = row.getValue(keyField) if row.getValue(keyField) in updateDict: row.setValue(testField1, updateDict[key][0]) row.setValue(testField2, updateDict[key][1]) row.setValue(testField3, updateDict[key][2]) row.setValue(testField4, updateDict[key][3]) row.setValue(testField5, updateDict[key][4]) row.setValue(testField6, updateDict[key][5]) uC.updateRow(row)
Also, if anyone is interested, here is the code to perform this operation for arbitrary tables (fields only defined once at the start):
How does that script compare with your former method; speed, reliability, etc.?
Hi Mark,It is not even necessary for you to list all the fields yourself, arcpy.ListFields(table) should do the trick. The purpose of what I had was (started off doing it, then forgot to carry it through) that you could have certain fields that were tested for matching while the other fields were just copied if there was a difference in the test fields, and of course for new entries...Regards,Stacy
testFields = arcpy.ListFields(masterTable)
testFields = ['APN_SUFFIX', 'TRA', 'NAME_1', 'NAME_2', 'MAIL_ADDR', 'CTY_STA']
subsetDict[row.getValue(keyField)] = [row.getValue(field) for field in testFields]
testFields = [] for fields in arcpy.ListFields(masterTable): testFields.append(fields.name)
Hi Mark,You will need to append the field name to the 'testFields' list. Try:testFields = [] for fields in arcpy.ListFields(masterTable): testFields.append(fields.name)
row.setValue(field, subsetDict[key])
keyFields = arcpy.ListFields(masterTable) oidIndex = keyFields.index('OBJECTID') # or whatever the offending field is... del keyFields[oidIndex]
for i in range(len(otherFields)): field = otherFields print fields.name row.setValue(field, subsetDict[key])
# define fields keyField = 'APN' otherFields = [] for fields in arcpy.ListFields(subsetTable): otherFields.append(fields.name) oidIndex = otherFields.index('OID') del otherFields[oidIndex]
Los miembros registrados pueden publicar, seguir actualizaciones y más. ¿Nuevo aquí? Regístrate gratis.
Find useful guides, FAQs, and documents to help you navigate and make the most of Esri Community.