I am working on a add-on button that i would like to be able to click on a parcel and create a point where i click and i need the new populate with the Parcels attributes.
I currently have two scripts that work, one creates the point and the other does spatial join and populates the selected point with the tax parcels attributes but the point has to already be there and selected. I need to be able to combine the two scripts into one. I think my biggest problem is that i don't know how to select the point once it's created to be able to spatial join and update the point with the Parcels attributes. I would gratefully appreciate any help on combining these two.
My initial try was to use the sort to get the highest AddressID which was created in the first script (CC_list.sort()) and then was going to use selecLayerByLocation to select the parcel to do the spatial join with the point but nothing is selected.
for row in sorted(arcpy.da.SearchCursor(fc, ["OBJECTID", "AddressID"]),reverse=True): mostRecentOID=row[0] mostRecentAddressID=row[1] break #Select parcel within selected Address Points arcpy.SelectLayerByLocation_management(polygonLayer, "INTERSECT", pointGeom)
Create point script
import arcpy from arcpy import env import time import datetime # Allow overwrite arcpy.env.overwriteOutput = True arcpy.env.qualifiedFieldNames = False arcpy.env.workspace = r"Database Servers\DSD15_SQLEXPRESS.gds\TwoWay (VERSION:dbo.DEFAULT)" # Script user input parameters #pointLayer = "TEST.DBO.CCAPTEST" #pointlayer fc = "TEST" # 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() input = arcpy.GetParameterAsText(0) rows = arcpy.SearchCursor(input) for row in rows: geom = row.Shape X = geom.centroid.X Y = geom.centroid.Y del rows CC_list = [] with arcpy.da.SearchCursor(fc, ["AddressID"]) as cursor: for row in cursor: try: if "CC" in row[0]: CC_list.append(int(row[0].strip("CC"))) except TypeError: pass del cursor CC_list.sort() AddressID = CC_list[-1] + 1 AddressID = 'CC' + str(AddressID) pointGeom = arcpy.PointGeometry(arcpy.Point(X, Y)) row_values = [(X, Y, (X, Y), AddressID)] cursor = arcpy.da.InsertCursor(fc, ["POINT_X", "POINT_Y", "SHAPE@XY", "AddressID"]) for row in row_values: cursor.insertRow(row) #del cursor # Stop the edit operation. edit.stopOperation() # Stop the edit session and save the changes edit.stopEditing(True) arcpy.RefreshActiveView()
Spatial join Update point attributes script.
# Import arcpy module import arcpy # Allow overwrite arcpy.env.overwriteOutput = True # Script user input parameters polygonLayer = "Taxparcels" pointLayer = "TEST" #Point Layer arcpy.env.workspace = r"Database Servers\DSD15_SQLEXPRESS.gds\TwoWay (VERSION:dbo.DEFAULT)" poly = "ACCOUNT_1" Pnt = "Account" sjpoints = "In_memory\sjpoints" parcelsCount = int(arcpy.GetCount_management(pointLayer).getOutput(0)) dsc = arcpy.Describe(pointLayer) selection_set = dsc.FIDSet if len(selection_set) == 0: print "There are no features selected" elif parcelsCount >= 1: #Run the Spatial Join tool, using the defaults for the join operation and join type arcpy.SpatialJoin_analysis(pointLayer, polygonLayer, sjpoints) # define the field list from the spatial join sourceFieldsList = ["TARGET_FID", poly,"ACCOUNT_1","SiteAddres_1",'SiteNum_1', 'SiteStreet_1','SiteNumSfx_1','Predir_1','SiteStreet_1', 'StreetType_1', 'Postdir_1', 'SiteCity_1', 'SiteZIP_1', 'OwnerName_1'] # define the field list to the original points updateFieldsList = ["OID@", Pnt,"Account","SiteAddres", 'SiteNum', 'StreetName', '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() manualFields = ["FacltyType", "StructType", "Verified", "Status", "StructCat", "APA_CODE", "ACCOUNT", 'SiteStreet'] with arcpy.da.UpdateCursor(pointLayer, manualFields) as rows: for row in rows: row[0] = ("Single Family Home") row[1] = ("Primary, Private") row[2] = ("Yes, GRM, TA") row[3] = ("Active") row[4] = ("Residential") row[5] = ("1110") rows.updateRow(row) del row del rows # populate the dictionary from the polygon valueDict = {r[0]:(r[1:]) for r in arcpy.da.SearchCursor(sjpoints, sourceFieldsList)} with arcpy.da.UpdateCursor(pointLayer, 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)
Solved! Go to Solution.
Try something like below.
#import modules import arcpy """ tool box parameters point param = feature set targetpoint = featurelayer parcel = featurelayer """ point = arcpy.GetParameterAsText(0) targetpoint = arcpy.GetParameterAsText(1) parcel = arcpy.GetParameterAsText(2) parcel_lyr = 'parcel_lyr' for prow in arcpy.da.SearchCursor(point,'SHAPE@XY'): x,y = prow[0] del prow point1 = arcpy.Point(x, y) ptGeometry = arcpy.PointGeometry(point1) arcpy.MakeFeatureLayer_management(parcel,parcel_lyr) arcpy.SelectLayerByLocation_management(parcel_lyr,"INTERSECT",ptGeometry) fldList = ['TMS','OWNERNAME'] fldDict ={} if int(arcpy.GetCount_management(parcel_lyr).getOutput(0))==1: for parrow in arcpy.da.SearchCursor(parcel_lyr,fldList): for x in range(len(fldList)): fldDict[fldList]=parrow del parrow fldAttList = [] for x in range(len(fldList)): fldAttList.append(fldDict[fldList]) manualFields = ["FacltyType", "StructType", "Verified", "Status", "StructCat"] for fld in manualFields: fldList.append(fld) fixedAtts = ["Single Family Home","Primary, Private","Yes, GRM, TA","Active","Residential","1110"] for att in fixedAtts: fldAttList.append(att) fldAttList.append(point1) fldtuple = (fldAttList) fldList.append( 'SHAPE@XY') tprow = arcpy.da.InsertCursor(targetpoint,fldList) tprow.insertRow(fldtuple) del tprow
I think my workflow would be:
Get XY from user (for model builder: a feature set, from an addin get the mousedown XY)
Then use the XY to select by location the parcel
Make feature layer from selected
Use a search cursor to read the needed fields into a dictionary
Then use an insertcursor on the point file to insert the row with the data from dictionary
Thank you for the reply. I am trying to implement your suggestions but i come up with a fail.
current code.
import arcpy from arcpy import env # Allow overwrite arcpy.env.overwriteOutput = True arcpy.env.qualifiedFieldNames = False arcpy.env.workspace = r"Database Servers\DSD15_SQLEXPRESS.gds\TwoWay (VERSION:dbo.DEFAULT)" # Script user input parameters fc = "TEST" polygonLayer = "parcels" poly = "ACCOUNT"# Pnt = "Account"# input = arcpy.GetParameterAsText(0) rows = arcpy.SearchCursor(input) for row in rows: geom = row.Shape X = geom.centroid.X Y = geom.centroid.Y del rows # Create point inPoint = arcpy.PointGeometry(arcpy.Point(X,Y)) #Select parcel within selected Address Points arcpy.SelectLayerByLocation_management(polygonLayer, "INTERSECT", inPoint) # Make a layer from the feature class arcpy.MakeFeatureLayer_management(fc, "Par") # define the field list from the parcels sourceFieldsList = ["ACCOUNT", poly,"SiteAddres",'SiteNum', 'SiteStreet','SiteNumSfx','Predir','SiteStreet', 'StreetType', 'Postdir', 'SiteCity', 'SiteZIP', 'OwnerName'] # populate the dictionary will all selected polygons valueDict = {r[0]:(r[1:]) for r in arcpy.da.SearchCursor("Par", sourceFieldsList)} # define the field list to the points updateFieldsList = ["Account", Pnt,"SiteAddres", 'SiteNum', 'SiteStreet', 'SiteNumSfx','Predir','SiteStreet', 'StreetType', 'Postdir', 'SiteCity', 'SiteZip', 'OwnerName'] arcpy.da.UpdateCursor(inPoint, updateFieldsList) 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) rowInserter = arcpy.da.InsertCursor(fc, updateFieldsList) arcpy.da.UpdateCursor(fc, updateFieldsList) for row in rows: row[0] = ("Single Family Home") row[1] = ("Primary, Private") row[2] = ("Yes, GRM, TA") row[3] = ("Active") row[4] = ("Residential") row[5] = ("1110") rows.updateRow(row) rowInserter.insertRow(row) arcpy.RefreshActiveView()
Lets be specific...since the code can't be tested because the data is not provided, could you at least provide the error message. A 'fail' requires a reason and an error message should be given. It could be as simple as a 'syntax error line xxxxx' but it is revealing. And on that last note, a failure on a particular line sometimes mean the code failed a line or two up, so check for syntax errors or more specifically....logic errors
And on the ...logic note...
In lines 19- 23 you go to great lengths to cycle through a cursor getting X and Y coordinates, austensibly to use them in future work. However, you do nothing with them. In line 28 you DO create a point but it will only use the last X,Y pair that you had. So is your intent to use the last point in the dataset? or is it to cycle through the points one at a time, and do something with them. I will stop there until that issues is clarified.
I set this code up to be used in a model and assumed the fields would be the same names and types it should help you get started.
#import modules import arcpy """ tool box parameters point param = feature set targetpoint = featurelayer parcel = featurelayer """ point = arcpy.GetParameterAsText(0) targetpoint = arcpy.GetParameterAsText(1) parcel = arcpy.GetParameterAsText(2) parcel_lyr = 'parcel_lyr' for prow in arcpy.da.SearchCursor(point,'SHAPE@XY'): x,y = prow[0] del prow point1 = arcpy.Point(x, y) ptGeometry = arcpy.PointGeometry(point1) arcpy.MakeFeatureLayer_management(parcel,parcel_lyr) arcpy.SelectLayerByLocation_management(parcel_lyr,"INTERSECT",ptGeometry) fldList = ['TMS','OWNERNAME'] fldDict ={} if int(arcpy.GetCount_management(parcel_lyr).getOutput(0))==1: for parrow in arcpy.da.SearchCursor(parcel_lyr,fldList): for x in range(len(fldList)): fldDict[fldList]=parrow del parrow fldAttList = [] for x in range(len(fldList)): fldAttList.append(fldDict[fldList]) fldAttList.append(point1) fldtuple = (fldAttList) fldList.append( 'SHAPE@XY') tprow = arcpy.da.InsertCursor(targetpoint,fldList) tprow.insertRow(fldtuple) del tprow
Wes, that worked awesome for creating a point and updating the points attributes! but i am having trouble putting and uncertain on how to implementing the arcpy.da.update cursor into the point dictionary. I need to be able to add the manualFields into the point.
Thanks for you help Wes
manualFields = ["FacltyType", "StructType", "Verified", "Status", "StructCat", "APA_CODE", "ACCOUNT", 'SiteStreet', 'SHAPE@X', 'SHAPE@Y'] with arcpy.da.UpdateCursor(ptGeometry, manualFields) as rows: for row in rows: row[0] = ("Single Family Home") row[1] = ("Primary, Private") row[2] = ("Yes, GRM, TA") row[3] = ("Active") row[4] = ("Residential") row[5] = ("1110") rows.updateRow(row)
Try something like below.
#import modules import arcpy """ tool box parameters point param = feature set targetpoint = featurelayer parcel = featurelayer """ point = arcpy.GetParameterAsText(0) targetpoint = arcpy.GetParameterAsText(1) parcel = arcpy.GetParameterAsText(2) parcel_lyr = 'parcel_lyr' for prow in arcpy.da.SearchCursor(point,'SHAPE@XY'): x,y = prow[0] del prow point1 = arcpy.Point(x, y) ptGeometry = arcpy.PointGeometry(point1) arcpy.MakeFeatureLayer_management(parcel,parcel_lyr) arcpy.SelectLayerByLocation_management(parcel_lyr,"INTERSECT",ptGeometry) fldList = ['TMS','OWNERNAME'] fldDict ={} if int(arcpy.GetCount_management(parcel_lyr).getOutput(0))==1: for parrow in arcpy.da.SearchCursor(parcel_lyr,fldList): for x in range(len(fldList)): fldDict[fldList]=parrow del parrow fldAttList = [] for x in range(len(fldList)): fldAttList.append(fldDict[fldList]) manualFields = ["FacltyType", "StructType", "Verified", "Status", "StructCat"] for fld in manualFields: fldList.append(fld) fixedAtts = ["Single Family Home","Primary, Private","Yes, GRM, TA","Active","Residential","1110"] for att in fixedAtts: fldAttList.append(att) fldAttList.append(point1) fldtuple = (fldAttList) fldList.append( 'SHAPE@XY') tprow = arcpy.da.InsertCursor(targetpoint,fldList) tprow.insertRow(fldtuple) del tprow
Sorry to keep bugging but i just noticed that the code doesn't populate the AddressID, POINT_X, POINT_Y fields. I tried to include into your code but i am unable to work.
I also need to populate field "StreetName" on the point from the Parcels, but the Parcels has the two fields SiteStreet & StreetType. I need to take the two fields SiteStreet & StreetType from the parcels and insert them together into the StreetName of the point.
#import modules import arcpy """ tool box parameters point param = feature set targetpoint = featurelayer parcel = featurelayer """ point = arcpy.GetParameterAsText(0) #point boolen targetpoint = "Test1" #target point feature class parcel = "TaxParcels" #target feature class parcel_lyr = 'parcel_lyr' for prow in arcpy.da.SearchCursor(point,'SHAPE@XY'): x,y = prow[0] del prow point1 = arcpy.Point(x, y) ptGeometry = arcpy.PointGeometry(point1) CC_list = [] with arcpy.da.SearchCursor(fc, ["AddressID"]) as cursor: for row in cursor: try: if "CC" in row[0]: CC_list.append(int(row[0].strip("CC"))) except TypeError: pass del cursor CC_list.sort() AddressID = CC_list[-1] + 1 AddressID = 'CC' + str(AddressID) arcpy.MakeFeatureLayer_management(parcel,parcel_lyr) arcpy.SelectLayerByLocation_management(parcel_lyr,"INTERSECT",ptGeometry) fldList = ['ACCOUNT','OWNERNAME','SiteAddres','SiteNum','SiteNumSfx','Predir','SiteStreet', 'StreetType', 'Postdir', 'SiteCity', 'SiteZip', 'OwnerName'] fldDict ={} if int(arcpy.GetCount_management(parcel_lyr).getOutput(0))==1: for parrow in arcpy.da.SearchCursor(parcel_lyr,fldList): for x in range(len(fldList)): fldDict[fldList]=parrow del parrow fldAttList = [] for x in range(len(fldList)): fldAttList.append(fldDict[fldList]) manualFields = ["FacltyType", "StructType", "Verified", "Status", "StructCat", "APA_CODE"] for fld in manualFields: fldList.append(fld) fixedAtts = ["Single Family Home","Primary, Private","Yes, GRM, TA","Active","Residential","1110"] for att in fixedAtts: fldAttList.append(att) fldAttList.append(point1) otherFields = ["X_Coord", "Y_Coord", "SHAPE@XY", "ADDRESSID"] for oth in otherFields: fldAttList.append(point1) fldtuple = (fldAttList) fldList.append( 'SHAPE@XY') tprow = arcpy.da.InsertCursor(targetpoint,fldList) tprow.insertRow(fldtuple) del tprow
Could you lay this out a little simpler for me?
Would give me a list of fields from your parcels you want to transfer to the point feature class and give me the fields they go to in the point feature class and give me a list of the preset data and the fields they go to.
list of fields from parcels that i need to transfer to point feature that are the same fields as the point feature class.
ACCOUNT, SiteAddres, SiteNum, SiteNumbSfx, Predir, Predir, SiteStreet, StreetType, Postdir, SiteCity, SiteZip, OwnerName, SubName. The point feature class has a field called "StreetName" that i need populate from two fields from the parcels and they are "SiteStreet" & StreetType". I also need to populate the fields called "AddressID" (unique Identifier) I currently have this working with the code below. the only thing that i need to do is populate the fields "POINT_X" and "POINT_Y" with x,y coordinates.
Thanks for the explanation of the code i was about to ask if you can explain it. I don't quiet understand the loops and python dictiionarys, and going field list and populating the dictionary with the field name and the matching attribute. you mentioned using a else statement below so if there was more or less than 1, could you show how this works with the current code?, so i could click on multiple parcels to create new address points? this would be handy of i need to create multiple points for new subdivisions. can you also attach a copy of the model that you use for please.
#import modules import arcpy """ tool box parameters point param = feature set targetpoint = featurelayer parcel = featurelayer """ arcpy.env.qualifiedFieldNames = False point = arcpy.GetParameterAsText(0) #point boolen targetpoint = "CCAP1" #target point feature class parcel = "parcels" #target feature class parcel_lyr = 'parcel_lyr' for prow in arcpy.da.SearchCursor(point,'SHAPE@XY'): x,y = prow[0] del prow point1 = arcpy.Point(x, y) ptGeometry = arcpy.PointGeometry(point1) CC_list = [] with arcpy.da.SearchCursor(targetpoint, ["AddressID"]) as cursor: for row in cursor: try: if "CC" in row[0]: CC_list.append(int(row[0].strip("CC"))) except TypeError: pass del cursor CC_list.sort() AddressID = CC_list[-1] + 1 AddressID = 'CC' + str(AddressID) arcpy.MakeFeatureLayer_management(parcel,parcel_lyr) arcpy.SelectLayerByLocation_management(parcel_lyr,"INTERSECT",ptGeometry) fldList = ['ACCOUNT','OwnerName','SiteAddres','SiteNum','siteNumSfx','Predir','SiteStreet', 'StreetType', 'Postdir', 'SiteCity', 'SiteZip'] fldDict ={} if int(arcpy.GetCount_management(parcel_lyr).getOutput(0))==1: for parrow in arcpy.da.SearchCursor(parcel_lyr,fldList): for x in range(len(fldList)): fldDict[fldList]=parrow del parrow fldAttList = [] for x in range(len(fldList)): fldAttList.append(fldDict[fldList]) manualFields = ["SiteState","FacltyType", "StructType","GIS_STEW", "UpdateBy","Verified", "Status", "StructCat", "APA_CODE","AddressID"] for fld in manualFields: fldList.append(fld) fixedAtts = ["ID","Single Family Home","Primary, Private","CanyonCo", "TA", "Yes, GRM, TA","Active","Residential","1110",AddressID, ] for att in fixedAtts: fldAttList.append(att) fldAttList.append(point1) fldtuple = (fldAttList) fldList.append( 'SHAPE@XY') tprow = arcpy.da.InsertCursor(targetpoint,fldList) tprow.insertRow(fldtuple) del tprow