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.
Man that's great you were able to get all that in If i read correctly the only thing you needed were the Point_X and Point_Y fields I added them to code below.
#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", "POINT_X", "POINT_Y" ] for fld in manualFields: fldList.append(fld) fixedAtts = ["ID","Single Family Home","Primary, Private","CanyonCo", "TA", "Yes, GRM, TA","Active","Residential","1110",AddressID,x,y ] 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've commented the code to help you find out where you should place the pieces your wanting to add if you'll provide me with the requested information i will help you get it in the code.I’m on geonet to help others and to learn and in saying that I also feel compelled to try to teach. Because if you want to know something really well you should try to teach and in doing so you will greatly improve your own skill. If any one sees anything in my comments that are wrong or inconsistent with the use of the code or tool please do not be shy to comment. You will not hurt my feelings I am here to learn as much as I’m here to help.
commented code
######## #information you should add these pieces of information #Script name #the name of the script #Author #The author of the script #Date #date of creation it's also a good idea to add a date when you modify the #code and list as a revision with a description of what you did and why #Pseudo code #This would be your intial workflow thoughts to help you create the #code below* ######## #import modules import arcpy ######################################### #These are the parameter settings for your tool #tool box parameters #point = feature set #this will allow the user to give us the xy data #targetpoint = featurelayer #this will get the target point as a feature layer or feature layer #parcel = featurelayer #Same as above but if we could restrict to feature layer only we #wouldn't need to create a feature layer below ######################################### #This website gives you a description of how to use arcpy.GetParameterAsText() #http://resources.arcgis.com/en/help/main/10.1/index.html#//018v00000047000000 # Syntax GetParameterAsText (index) #You always put your variables at the top I don't know why #This is the point variable gained from the feature set the #only thing we need from here is the xy point = arcpy.GetParameterAsText(0) #The target point feature class this is where we want to get data to #you can call these variables anything you want but is always a good #idea to call it something that makes sense for your use targetpoint = arcpy.GetParameterAsText(1) #The parcel file this is where we will be getting data from parcel = arcpy.GetParameterAsText(2) #This variable is used with make feature layer because you can't select #by location from a feature class it needs to be a feature layer parcel_lyr = 'parcel_lyr' #This website gives you a description of how to use arcpy.da.SearchCursor #http://resources.arcgis.com/en/help/main/10.2/index.html#//018w00000011000000 #There are a couple of different search cursor with different uses I won't try to #explain them here I think it's sufficient that you are aware of them see this note #Note:arcpy.da.SearchCursor should not to be confused with the arcpy.SearchCursor. # Syntax SearchCursor (in_table, field_names, {where_clause}, {spatial_reference}, {explode_to_points}, {sql_clause}) for prow in arcpy.da.SearchCursor(point,'SHAPE@XY'): #The only thing we need is the x and y x,y = prow[0] #You should always delete the cursor #It often drives me crazy when I forget and can't read my data del prow #Not sure it's neccessary to do this part or not I probably could have created this #in the loop above something like point1 = prow[0] would most likely would have worked #maybe someone better than could chime in #I'm using it here so I can get the element needed for point geometry below point1 = arcpy.Point(x, y) #This website gives you a description of how to use arcpy.PointGeometry #http://resources.arcgis.com/en/help/main/10.2/index.html#//018z00000039000000 #Syntax PointGeometry (inputs, {spatial_reference}, {has_z}, {has_m}) #We'll use this in the select by location query ptGeometry = arcpy.PointGeometry(point1) #This website gives you a description of how to use arcpy.MakeFeatureLayer_management #http://resources.arcgis.com/en/help/main/10.2/index.html#//00170000006p000000 # Syntax MakeFeatureLayer_management (in_features, out_layer, {where_clause}, {workspace}, {field_info}) # We need to do this in case the user selects a feature class above instead of a feature layer arcpy.MakeFeatureLayer_management(parcel,parcel_lyr) #This website gives you a description of how to use arcpy.SelectLayerByLocation_management #http://resources.arcgis.com/en/help/main/10.2/index.html#//001700000072000000 # Syntax SelectLayerByLocation_management (in_layer, {overlap_type}, {select_features}, {search_distance}, {selection_type}) #Get the intesecting parcel so we can get the data arcpy.SelectLayerByLocation_management(parcel_lyr,"INTERSECT",ptGeometry) #We are using a field list to identify the fields we want to get from the parcel #layer I'm also using for a few shortcuts I'll explain those when we get to them fldList = ['TMS','OWNERNAME'] #We are creating a field dictionary here to hold the field names and the field data #this is a shortcut so I don't have to write out every field and every row. When #get to that part I'll give a description of how to do it the other way and with #needing a concantination of fields in the insert cursor we may do it the other way #so you'll be able to see it fldDict ={} #We are simply making sure we are only dealing with one parcel #you could put an else statement below so if there was more or less than 1 #you could give the user a message letting them know that we got more or less #than expected so we wont transfer any data or create a point in the targetpoint if int(arcpy.GetCount_management(parcel_lyr).getOutput(0))==1: #This is another searchcursor see above for parrow in arcpy.da.SearchCursor(parcel_lyr,fldList): #You can find explinations of for loops and python dictiionarys all over the #web. basically we are iterating through the field list and populating #the dictionary with the field name and the matching attribute for x in range(len(fldList)): fldDict[fldList]=parrow #again delete the cursor del parrow #we are creating a field attribute list to use below fldAttList = [] #Populating the field attribute list with the attributes from the dictionary for x in range(len(fldList)): fldAttList.append(fldDict[fldList]) #These are the manual fields we'll need to add them to the list of fields manualFields = ["FacltyType", "StructType", "Verified", "Status", "StructCat"] #We will probably change these out with a different set of fields for the target #feature class for fld in manualFields: fldList.append(fld) #These are the attributes for the manual fields fixedAtts = ["Single Family Home","Primary, Private","Yes, GRM, TA","Active","Residential","1110"] #Add the above attributes to the attributes list for att in fixedAtts: fldAttList.append(att) #add the coordinates to the list so the point can be created fldAttList.append(point1) #convert field attribute list to a tuple fldtuple = (fldAttList) #Add the xy field so the insert cursor knows where to put the coordinates fldList.append( 'SHAPE@XY') #This website gives you a description of how to use arcpy.da.InsertCursor #http://resources.arcgis.com/en/help/main/10.2/index.html#//018w0000000t000000 # Syntax InsertCursor (in_table, field_names) #Note:arcpy.da.InsertCursor should not to be confused with arcpy.InsertCursor. tprow = arcpy.da.InsertCursor(targetpoint,fldList) tprow.insertRow(fldtuple) #again delete the cursor del tprow
That is the weirdest thing. I added the "POINT_X", "POINT_Y" and x,y to the same lines as you did but i got an error but now that i copied and pasted what you have i got it to work, kind of for some weird reason i have "10" in the "POINT_x" field. I know that is not correct. also the point feature class has a field called "StreetName" that i need populate from two fields from the parcels and they are "SiteStreet" & StreetType".
as far as my other quesitons, would you like me to start a different post?
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.
I've attached the code with the else statement in it with a simple message returned to the user, I also included the tool used. As far as creating multiple points for doing a subdivision i think i would start a new script and get it to work and either use as stand alone tool or incorporate into this tool. I think i would more lean towards using it as a stand alone, but that's just my opinion. You may also want to look into LGIM sounds like your doing address points and there some tools that work with the LGIM that will help with creating address points, not to mention a good format for storing your data.
Wes, thank you for all your help.
You are welcome