Select to view content in your preferred language

Select points and update attributes base on parcels

6070
14
Jump to solution
07-08-2015 01:35 PM
CCWeedcontrol
Frequent Contributor

I am working a code/button that will help me update address points attributes based on the parcel they are in.

I am trying to to use filed list to create a mach and update the points with dictionaries. I don't not get error but my address points don't get updated from the parcels. I would appreciate any help with my code.

import arcpy       
from datetime import datetime as d       
startTime = d.now()       


#set to folder where features are located       
arcpy.env.workspace = r"Database Servers\DSD15_SQLEXPRESS.gds\TEST (VERSION:dbo.DEFAULT)" #r"Database Servers\DSD15_SQLEXPRESS.gds\TonyTwoWay (VERSION:dbo.DEFAULT)" #on windows use \ instead of /       
arcpy.env.overwriteOutput = True
arcpy.env.qualifiedFieldNames = False


#define variables for cursor       
#---------------------------       
FC = "TEST.DBO.CCAPTEST"  #pointlayer     
TaxPar = "TaxParcels" #Parcels
poly = "ACCOUNT"#'SiteAddres_1','SiteAddres_1', 'SiteNum_1', 'SiteNumSfx_1','Predir_1','SiteStreet_1', 'StreetType_1', 'Postdir_1', 'SiteCity_1', 'SiteZIP_1', 'OwnerName_1' 
Pnt =  "Account"#
TaxPar1 = "selectedParcels"


parcelsCount = int(arcpy.GetCount_management(FC).getOutput(0))     
    
dsc = arcpy.Describe(FC) 
selection_set = dsc.FIDSet         
if len(selection_set) == 0:       
    print "There are no features selected"  
             
elif parcelsCount >= 1:
    
    #Select parcel within selected Address Points
    int(arcpy.GetCount_management(FC).getOutput(0))
    arcpy.SelectLayerByLocation_management(TaxPar, "CONTAINS", FC)


    #Create in memory parcel layer  
    selectedParcels = arcpy.MakeFeatureLayer_management(TaxPar, TaxPar1)



    arcpy.SelectLayerByAttribute_management(TaxPar1, "NEW_SELECTION", "OBJECTID= "+OID)
    
    # define the field list from the parcels
    sourceFieldsList = ["ACCOUNT", poly,"SiteAddres",'SiteNum', 'SiteStreet','SiteNumSfx','Predir','SiteStreet', 'StreetType', 'Postdir', 'SiteCity', 'SiteZIP', 'OwnerName']    


    # define the field list to the points
    updateFieldsList = ["Account", Pnt,"SiteAddres", 'SiteNum', 'SiteStreet', 'SiteNumSfx','Predir','SiteStreet', 'StreetType', 'Postdir', 'SiteCity', 'SiteZip', 'OwnerName']
    
    # Start an edit session. Must provide the workspace.    
    edit = arcpy.da.Editor(arcpy.env.workspace)    
  
    # Edit session is started without an undo/redo stack for versioned data    
    #  (for second argument, use False for unversioned data)    
    edit.startEditing(True)    
  
    # Start an edit operation    
    edit.startOperation()                


    # populate the dictionary from the polygon
    valueDict = {r[0]:(r[1:]) for r in arcpy.da.SearchCursor(TaxPar1, sourceFieldsList)}    


    with arcpy.da.UpdateCursor(FC, updateFieldsList) as updateRows:    
        for updateRow in updateRows:    
            keyValue = updateRow[0]
            if keyValue in valueDict:    
                for n in range (1,len(sourceFieldsList)):      
                    updateRow = valueDict[keyValue][n-1]
                updateRows.updateRow(updateRow) 
    # Stop the edit operation.    
    edit.stopOperation()
    # Stop the edit session and save the changes
    edit.stopEditing(True)


arcpy.RefreshActiveView()
#arcpy.Delete_management(sjpoints)
0 Kudos
14 Replies
RichardFairhurst
MVP Alum

My code automatically closes the session already, since I use the "with" syntax.  The help says "The with statements act as context managers and handle the appropriate start, stop, and abort calls for you.".

As far as nothing happening, have you verified that the Account of the address point and the parcel are the same before running the tool?  If not then the flaw is in the approach you are taking, not the code itself.

To catch errors enclose the code in a Try Except block like this:

try:

### All code beginning with line 5 (indented)###

except Exception as e:   
    # If an error occurred, print line number and error message   
    import traceback, sys   
    tb = sys.exc_info()[2]   
    print("Line %i" % tb.tb_lineno)
    arcpy.AddMessage("Line %i" % tb.tb_lineno)
    print(e.message)
    arcpy.AddMessage(e.message)

If no errors get reported I will need more info about your test data.

CCWeedcontrol
Frequent Contributor

Richard,

i was getting the ArcMap drawing errors the request operation is invalid on a close state. I removed the "with" from line 39 and replaced with the edit = arcpy.da.Editor(arcpy.env.workspace) edit.startEditing and edit.startOperation and i did not the the close state error.

I did notice that for some address point the attributes were updated with the same attributes. I have attached a picture of two parcels that have different "ACCOUNT" & "siteNum number from each other. I select the point on south parcel and run the code and seems to run fine but then i select the address point of the parcel above and it populates with the info from the south parcel.. weird

0 Kudos
RichardFairhurst
MVP Alum

It would help if you could post an image that showed the Address Points table with the updated points selected so I could see what had changed and what the point Account Numbers were.

To check what is going on with the dictionary and cursor add some print statements.  After the valueDict is created you should add:

print valueDict

and after getting the keyValue assigned you should add:

print keyValue

CCWeedcontrol
Frequent Contributor

Richard,

I recreated the database and re-ran the code and it ran fine. some how the address point database got corrupted.

Now if the address point did not an have attribute in the "Account" field this would not work because there is nothing to match with the Parcels "ACCOUNT" attribute. So would a spatial join work in a situation where the address point does not have an attribute in the "Account" field.

Thanks for your help!

0 Kudos
RichardFairhurst
MVP Alum

Yes.  A Spatial Join that uses the One To Many option and that makes the points the target and the parcels the join features would create a link by tracking the ObjectIDs of the point and linking it to the parcel fields in the Spatial Join output.  The Spatial Join field map should keep the parcel fields that you need and eliminate the point fields to avoid confusing you with their duplicate field names (Use Model Builder to set the field map up of the Spatial Join tool in a model and export the model to a Python script to get the field map string correct).  The TARGET_FID (point ObjectID) would be the dictionary key and would store the parcel fields captured by the Spatial Join.  The Point ObjectId would make sure the correct point is updated by the cursor and would always get the Account number of the parcel that contained it no matter what the point Account number was originally.

0 Kudos