|
BLOG
|
It does not show the right side of the screen shot in Geonet, so I did not see the settings. I see nothing wrong with your inputs. Do my second instruction by selecting one set of points for a single Demand_6 value manually and remove Demand_6 from the Case field (leave it blank). Then run it again and let me know what happened. You also should try the minimum k setting, since the tool increases the k factor when it needs to automatically. Several of your sets look like the whole set is not much over 30 points, so a k of 30 is too high when you get to sets with fewer than about 60 points. I have never used a k factor above 15 and wouldn't unless I had about 200 points minimum for the smallest case value.
... View more
08-07-2015
01:06 PM
|
0
|
0
|
13104
|
|
BLOG
|
Wally: Please open the tool and screen shot the settings you are entering before you run it. Also, what type of field is the Demand_6 field? I am guessing a Long based on the screen shot, but I want to confirm that. You could manually select a set of points for just one value in the Demand_6 field and try running the tool without a Case field to see if it can create any output. That way I may be able to more easily tell what part of the code is failing. If no obvious problem becomes apparent from those two actions then to trouble shoot this you will probably need to modify the code by adding some arcpy.AddMessage() lines to output a message when different parts of the code are completed to see how far the code gets before it fails. Once I know where the code is failing then hopefully I can identify a solution.
... View more
08-07-2015
11:55 AM
|
0
|
0
|
13104
|
|
BLOG
|
Very few tools are used in the script (MakeFeatureLayer_management, CreateFeatureclass_management, and AddField_management are the only tools I see being used) and all the tools used are available under a Basic license. All the rest of the code uses pretty standard arcpy geometry, array, cursor and dictionary processing, So unless the error message mentioned something about a license I doubt that is the issue. What error message appeared when the tool was rejected? What version of ArcGIS are you using? The toolbox probably is only compatible with ArcGIS 10.2 or above, since that is the version I used to build it. In fact I need to update the code to use the 10.1 version cursors to improve the speed of the tool, since it uses the outdated 10.0 version cursors that are very slow. But that means the core code would work if you only have 10.0. You might have to rebuilt the toolbox interface to make it work with an earlier version. Here is a screen shot of what the tool interface should look like when it opens properly:
... View more
08-06-2015
05:40 PM
|
0
|
0
|
13104
|
|
POST
|
The lines dictionary won't change, since it only has the line ID. The points dictionary can have any tuple for the key that you may want as long as the line ID is the first field in the tuple or at a known position in the key, so the look up of the line does not change. I see no real difference in the way the code would be structured other than what values reset the counter. So dct and dct2 would change but not valueDict. In any case with over 1 million points and probably thousands of lines you would wait days or months for an embedded cursor to finish. However, with that many points and lines you may run out of memory if you process the complete set into these dictionaries in one run. You have to create a loop surrounding my code and process queries in the outer loop to segment the line and point sets into smaller groups (say iterating through ranges of 500 line IDs in the lines and points) . The dictionaries would be cleared and reset in each loop so that your memory would not run out.
... View more
08-02-2015
01:47 PM
|
0
|
0
|
3354
|
|
POST
|
Your are wrong on how you should approach this problem. Embedded cursors are virtually never the solution to any problem. Use a dictionary to make the match between the line IDs and the points and then process one cursor normally. The larger your datasets get the embedded cursors slow down exponentially, while Dictionaries have a linear performance impact. So for 10000 points on 100 lines embedded cursors will perform at least 100 times slower than a dictionary lookup. Although I have not tested the code below, I believe it will work. The main part I am unsure of is the sort of dct that creates dct2. In any case, once all bugs are worked out this code will perform wonderfully. import arcpy
fc_pnt = r"C:\Forum\Fishing\test.gdb\fishingpoints"
fc_line = r"C:\Forum\Fishing\test.gdb\river"
fld_diststart = "DistStart"
fld_distprevious = "DistPrev"
# add fields to point featureclass in case they do not exist
add_flds = [fld_diststart, fld_distprevious]
for fld in add_flds:
if len(arcpy.ListFields(fc_pnt, wild_card=fld)) == 0:
arcpy.AddField_management(fc_pnt, fld, "DOUBLE")
fields = ["LINE_ID", "SHAPE@"]
# Create a dictionary of lines with their geometry
valueDict = {r[0]:(r[1:]) for r in arcpy.da.SearchCursor(fc_line, fields)}
dct = {}
flds = ["LINE_ID", "SHAPE@", "OID@", fld_diststart]
with arcpy.da.SearchCursor(fc_pnt, flds) as curs:
for row in curs:
line = row[0]
if line in valueDict:
polyline = valueDict[line]
pnt = row[1]
oid = row[2]
diststart = polyline.queryPointAndDistance(pnt, False)
dct[(line, oid)] = diststart[1]
del curs, row
# sort on distance and determine distance between points
dct2 = {}
cnt = 0
prevline = -1
for line_oid, diststart in sorted(dct.items(), key=lambda x: x[1]):
cnt += 1
if cnt == 1:
distbetween = 0
distprev = diststart
prevline = line_oid[0]
elif line_oid[0] != prevline:
distbetween = 0
distprev = diststart
prevline = line_oid[0]
else:
distbetween = diststart - distprev
distprev = diststart
dct2[line_oid] = distbetween
# update the points fc
flds = ("LINE_ID", "OID@", fld_diststart, fld_distprevious)
with arcpy.da.UpdateCursor(fc_pnt, flds) as curs:
for row in curs:
line = row[0]
oid = row[1]
if (line, oid) in dct:
row[2] = dct[(line, oid)]
row[3] = dct2[(line, oid)]
curs.updateRow(row)
del curs, row
... View more
08-01-2015
02:49 PM
|
1
|
10
|
6678
|
|
POST
|
What database are you using? If it is Access then I would expect funky SQL behaviors. File geodatabases and SDE is all I will use for actual work. Like with a Long field does not work with a File Geodatabase. I just tried it in ArcMap 10.3 and got an error. The explicit cast syntax I provided is not a work around. It is the proper SQL syntax for what you want to do. Like is always described as a String operator and throwing an error is the proper implementation when Like is used directly with a Long field. An implicit cast is not supposed to occur, and if it does occur for you the program is effectively inserting the cast I wrote out behind the scenes for you, which will never be a consistent behavior. The behavior you desire is the work around to a standard SQL implementation.
... View more
07-31-2015
04:33 PM
|
0
|
0
|
8497
|
|
POST
|
The field type was always an issue as far as I know in ArcMap. Like has never never been officially supported with a long field in any recognized SQL I know of, and Esri tries to comply with recognized SQL standards in general. If it did not throw an error before then the Esri implementation was flawed and would not be portable outside of ArcMap. I have always had to cast the long field to a text field to use any string comparisons such as the LIKE operator. Even though ArcMap 10.3 includes LIKE in the query builder, it throws an error when I actually try to use Like in combination with a Long field, so it does not work in ArcMap and never should have worked. For a File geodatabase you would use this syntax to cast your long field to a string (making the number of characters fit your expected long values): CAST(Long_Field AS CHARACTER(50)) LIKE '114%' SQL like this cannot be converted to the Clause mode. If you want to convert a text field with numbers to a numeric value so you can use mathematical expressions or numeric comparisons you would cast the value to a Float: CAST(Text_Field AS FLOAT) <= Long_Field This SQL could not be converted to Clause mode either.
... View more
07-31-2015
01:43 PM
|
0
|
2
|
8497
|
|
POST
|
What version of ArcGIS Pro are you using? At version 1.1 the clauses that use LIKE in SQL mode are Begins With ('114%'), Ends With ('%114') and contains the text ('%114%'). The field has to be a text field to show these options. If I type the equivalent syntax for one of the Clause types in SQL mode it shows the correct Clause for each option when I switch back to Clause mode. If I put in the expression Field LIKE '%1%14' in SQL mode the expression is accepted, but I cannot switch back to Clause mode, and it gives a message that "The expression cannot be edited in Clause mode". I did not try this at version 1.0, so it may not have been available in that release (although I have no idea why it wouldn't have been included if it was missing)..
... View more
07-31-2015
08:50 AM
|
2
|
4
|
8497
|
|
POST
|
Automation requires strict rules that can be broken down. Expect 20 steps or more for a complex operation like this. You may have to over bound, then trim, then refine, then reexamine, then reprocess, etc. Don't even begin to think this is a one or two tool process. To begin, of the things you tried, what got you the closest to your end goal for about 80% of your groups or for your least complex cane field? If you want help it is a good idea to show us what a particular tool produced and then point out what you would change if you had the ability to create your own tool. The tool itself is following rules that most of us understand and we can then see where you would have to break those rules and rewrite the tool's rules to get it to do what you want. I see no rule that accounts for why 009B would ever result in a shape like the one you have drawn. Nothing you have said so far would have lead me to ever draw that. Why does it take any of the white area into its boundary when the others don't? Unless you can explain it to another human you have no hope of getting a computer to follow your rule. If you have areas with no data or low quality data that you want to "get precise" it is unlikely to happen without creating precise data to work with manually. You probably will only be able to get 80% to 90% of this automated, and the other 10% to 20% will take 100 times as much effort. Aim to fix the 80% to 90% first, then worry about the 10% to 20%. With very complex operations I find that there is always at least 10% that you have to process manually, because they have individualized rules that are both difficult to break down and that would account for such a small set that they are inefficient to automate. In the end you may just end up living with the hard stuff being inaccurate once you can figure out the level of effort it would take to fix it.
... View more
07-21-2015
06:16 AM
|
1
|
0
|
2136
|
|
BLOG
|
Google has added 25 million buildings in the United States this year to their Map view. These building outlines can be converted to polygons in ArcGIS if you have Photoshop and do the following steps: 1. Locate an area with buildings in Google Maps with the Map view on. Maximize the browser window. Zoom until you are at least at the second level zoom above the minimum level to make the buildings appear to get enough resolution. 2. Press the Alt+Prt Scr buttons on the keyboard to get a screen shot (or use your favorite screen shot software). 3. Open Photshop and create a new project (on the menu use File -> New or press Ctrl+N). 4. Paste the screenshot into the Photoshop project (on the menu use Edit -> Paste or Ctrl+V). 5. From the Menu choose Select -> Color Range… (I added a custom keyboard shortcut of Alt+Shift+Ctrl+R) 6. With the Select option set to Sampled Color click the eyedropper cursor on the center of a building. Check the inverse option. Press the OK button. 7. With the selection still active create a new layer (on the menu use Layer -> New -> Layer… or press Shift+Ctrl+N). Name the layer Building Background and press the OK button. 8. Add a fill to the layer (from the menu use Edit -> Fill… or press Shift+F5). Choose the Mode “Black” and press the OK button. 9. Deselect everything by pressing Ctrl+D. From the menu choose Select -> Color Range... (I added a custom keyboard shortcut of Alt+Shift+Ctrl+R). With the Select option set to Sampled Color click the eyedropper cursor on the center of a building. Press the OK button. 10. With the selection still active create a new layer (on the menu use Layer -> New -> Layer… or press Shift+Ctrl+N). Name the layer Building Foreground and press the OK button. 11. Add a fill to the layer (from the menu use Edit -> Fill… or press Shift+F5). Choose the Mode “White” and press the OK button. 12. You should now have a Black and White image. The outlines of the roads will have areas with white pixels that need to be painted out. Set the palette color to Black. Right click on the map and choose a paint brush size that fits comfortably within the roadway (about 40 pixels). Paint out the small white pixels. Also paint out partial buildings on the edges of the map. 13. On the menu choose Image -> Mode -> Grayscale… (I added a custom keyboard shortcut to the Grayscale option of Alt+Shift+Ctrl+G) and then choose to not Flatten the image and to Discard the Color information. 14. Save the photoshop project as a BMP. Use 8 Bit depth (if it says higher depths you have a problem). 15. Open a new ArcMap session and just add aerials or a satellite basemap. 16. Right click the Date Frame and chose Date Frame Properties. On the Freme tab choose the background to be black. 17. Locate the same set of buildings on the aerial. 18. Add the BMP you saved in step 14. Say OK to the warning about the image not being spatially referenced. 19. Change the BMP layer transparency to 50%. 20. Right click the BMP layer and Zoom to Layer. 21. Open the Georeferencing toolbar. 22. Press the Add Control Points button and choose a corner of a building that you can match to the aerial. 23. Press the Back button to return to the aerial and set the control point at the corner of the same building on the aerial. 24. Set another control point that is vertical or horizontal to the previous point, not diagonal. 25. Set additional control points if necessary, but not more than 4 total points. 26. When you are satisfied with the georeferencing position on the toolbar choose Georeferencing -> Update Georeferencing. 27. Set the BMP transparency to 0% and turn off the aerials. 28. Open the Toolboxes -> System Toolboxes -> Conversion Tools Toolbox -> From Raster Toolset -> Raster to Polygon tool. 29. Choose the bmp as the input and set the output location and name to a geodatabase feature class and press OK. 30. Start an editor session on the polygon layer you just created and delete the background polygon. 31. Open the Table View for the new polygon feature class and sort by shape area. Choose any very small polygons that are not buildings that you did not paint out and delete them. 32. Set up a permanent feature class that you will append all new buildings to or append this set of buildings to the feature class you set up previously. The result shown below created 115 building outline polygons (the polygons are set to hollow with a red outline that is 3 points thick).
... View more
07-18-2015
12:25 AM
|
4
|
3
|
15163
|
|
POST
|
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.
... View more
07-09-2015
11:26 AM
|
0
|
0
|
1670
|
|
POST
|
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
... View more
07-09-2015
10:26 AM
|
2
|
2
|
1670
|
|
POST
|
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.
... View more
07-09-2015
09:16 AM
|
1
|
4
|
1670
|
|
POST
|
The variable OID is not assigned a value as far as I can see. So line 40 is selecting nothing. But SelectLayerByAttribute is unnecessary. If you are writing to SDE data that is versioned then you do need to do the Editor operation. However, you should use the with syntax to get errors reported and automated closure of the session Also, you over complicating this and you are creating unnecessary selections. Selections inside selections is just another embedded loop and is BAD. Don't do that. Just use a dictionary and load every selected parcel into it all at once. It will do the Account look up 100 times faster than SelectLayerByAttribute. So use the code below. I based this on your code. Your code assumes that Account in the address points already matches Account in the Parcels and that no two parcels have the same Account. If the Account of the Address that touches a parcel is not the same as the Account on the parcel then the update cursor won't work. If the real match is only spatial then this code approach won't work. Also if two addresses have the same Account and fall on two parcels with the same accounts, the result will just use the last parcel with that account that is read and not necessarily the parcel touched by the address. For a pure spatial match I would do a Spatial Join with the One To Many option to an in_memory fc, not SelectLayerByLocation. The Spatial Join is much faster and more reliable for spatial matching than any attribute that may or may not be spatially related. The Spatial Join result would have the necessary ObjectID values to use the cursor for the transfer. 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"#
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
arcpy.SelectLayerByLocation_management(TaxPar, "CONTAINS", FC)
# 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(TaxPar, sourceFieldsList)}
# 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.
with arcpy.da.Editor(arcpy.env.workspace) as edit:
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)
arcpy.RefreshActiveView()
... View more
07-08-2015
04:27 PM
|
3
|
6
|
3107
|
|
BLOG
|
I have wanted tools in ArcMap that let me do more things with Standalone Tables. For example, there is no tool that will let me duplicate records in a Standalone Table or insert a row directly into an existing Standalone Table that came from the tabular portion of a feature. I cannot Copy/Paste rows or features into a Standalone Table at all like I can with features in a Feature Class. Even for features using Copy/Paste is slow and can only be done in an edit session. The Append tool works for table to table inserts or feature class to feature inserts, but only if the input and output are different from each other. The Append tool also will not let me take the tabular data of a feature and append it into an existing Standalone Table. I wanted a tool that would quickly do inserts and work for Feature Class to Feature Class, Feature Class to Table, or Table to Table inserts. I also wanted the selection behavior to be similar to the Copy/Paste behavior. I wanted the tool to only work when records are first selected, and I wanted the selected records of the input to be cleared and the newly inserted records in the target to be selected when the tool finishes. That is especially useful when the input and the target are the same table or feature class. I also wanted the tool to automatically match fields like Copy and Paste does. The field matching behavior is similar to using the default field map that appears in the Append tool when the NO TEST option is chosen, so the schemas don't have to match exactly. However, unlike the Append tool, the Insert Selected Features or Rows tool does not support multiple inputs and does not support customized field mapping. An edit session should not be active if the data is versionsed, since arcpy cannot connect to an active edit session. The tool will internally start and stop an edit session when versioned data is involved. If data in not versioned an edit session may be active, but is not necessary. When an edit session is active for unversioned data, if the edit session is stopped before saving the inserts then the inserts will disappear without warning and will not be saved. The tool lets you specify the number of copies of each feature or row you want to insert into the target layer or table view. The minimum number of copies is 1, and 1 is the default value. NOTE: If the table view of the target is open when the tool is run, then the Append tool and my tool are affected by an Esri bug. The records are inserted, but the total record count of the table view does not update and the newly inserted records cannot be accessed or seen when Show all records view is active. However, since the inserted records are selected by my tool, after the tool completes the selected records count of the table view is updated and the new records do appear when the Show selected records view is active. To fully refresh the table view to show the new records in the Show all records view mode either the table view has to be closed and reopened or a field has to have its values sorted. The attached python toolbox includes the code for the tool and the tool help files. I recommend that you save the attached toolbox in your "%APPDATA%\ESRI\Desktop10.2\ArcToolbox\My Toolboxes" directory. The toolbox also Includes my Multiple Field Key to Single Field Key tool for 10.2. For more on that tool see my blog here. The code for the tool is shown below: # Author: Richard Fairhurst
# Date: July 2015
import arcpy
class Toolbox(object):
def __init__(self):
"""Define the toolbox (the name of the toolbox is the name of the
.pyt file)."""
self.label = "Field Match Tools"
self.alias = ""
# List of tool classes associated with this toolbox
self.tools = [InsertSelectedFeaturesOrRows]
class InsertSelectedFeaturesOrRows(object):
def __init__(self):
"""Define the tool (tool name is the name of the class)."""
self.label = "Insert Selected Features or Rows"
self.description = ""
self.canRunInBackground = False
def getParameterInfo(self):
"""Define parameter definitions"""
# First parameter
param0 = arcpy.Parameter(
displayName="Source Layer or Table View",
name="source_layer_or_table_view",
datatype="GPTableView",
parameterType="Required",
direction="Input")
# Second parameter
param1 = arcpy.Parameter(
displayName="Target Layer or Table View",
name="target_layer_or_table_view",
datatype="GPTableView",
parameterType="Required",
direction="Input")
# Third parameter
param2 = arcpy.Parameter(
displayName="Number of Copies to Insert",
name="number_of_copies_to_insert",
datatype="GPLong",
parameterType="Required",
direction="Input")
param2.value = 1
# Fourth parameter
param3 = arcpy.Parameter(
displayName="Derived Layer or Table View",
name="derived_table",
datatype="GPTableView",
parameterType="Derived",
direction="Output")
param3.parameterDependencies = [param1.name]
param3.schema.clone = True
params = [param0, param1, param2, param3]
return params
def isLicensed(self):
"""Set whether tool is licensed to execute."""
return True
def updateParameters(self, parameters):
"""Modify the values and properties of parameters before internal
validation is performed. This method is called whenever a parameter
has been changed."""
return
def updateMessages(self, parameters):
"""Modify the messages created by internal validation for each tool
parameter. This method is called after internal validation."""
if parameters[1].value:
insertFC = parameters[1].value
strInsertFC = str(insertFC)
if parameters[0].value and '<geoprocessing Layer object' in strInsertFC:
FC = parameters[0].value
strFC = str(FC)
if not '<geoprocessing Layer object' in strFC:
print("Input FC must be a layer if output is a layer")
parameters[0].setErrorMessage("Input must be a feature layer if the Output is a feature layer!")
else:
dscFCLyr = arcpy.Describe(FC)
dscinsertFCLyr = arcpy.Describe(insertFC)
# add the SHAPE@ field if the shapetypes match
if dscFCLyr.featureclass.shapetype != dscinsertFCLyr.featureclass.shapetype:
print("Input and Output have different geometry types! Geometry must match!")
parameters[0].setErrorMessage("Input and Output do not have the same geometry")
if dscFCLyr.featureclass.spatialReference.name != dscinsertFCLyr.featureclass.spatialReference.name:
print("Input and Output have different Spatial References! Spatial References must match!")
parameters[0].setErrorMessage("Input and Output do not have the same Spatial References! Spatial References must match!")
if parameters[2].value <= 0:
parameters[2].setErrorMessage("The Number of Row Copies must be 1 or greater")
return
def execute(self, parameters, messages):
"""The source code of the tool."""
try:
mxd = arcpy.mapping.MapDocument(r"CURRENT")
df = arcpy.mapping.ListDataFrames(mxd)[0]
FC = parameters[0].value
insertFC = parameters[1].value
strFC = str(FC)
strInsertFC = str(insertFC)
FCLyr = None
insertFCLyr = None
for lyr in arcpy.mapping.ListLayers(mxd, "", df):
# Try to match to Layer
if '<geoprocessing Layer object' in strFC:
if lyr.name.upper() == FC.name.upper():
FCLyr = lyr
if '<geoprocessing Layer object' in strInsertFC:
if lyr.name.upper() == insertFC.name.upper():
insertFCLyr = lyr
if FCLyr == None or insertFCLyr == None:
# Try to match to table if no layer found
if FCLyr == None:
tables = arcpy.mapping.ListTableViews(mxd, "", df)
for table in tables:
if table.name.upper() == strFC.upper():
FCLyr = table
break
if insertFCLyr == None:
tables = arcpy.mapping.ListTableViews(mxd, "", df)
for table in tables:
if table.name.upper() == strInsertFC.upper():
insertFCLyr = table
break
# If both layers/tables are found then process fields and insert cursor
if FCLyr != None and insertFCLyr != None:
dsc = arcpy.Describe(FCLyr)
selection_set = dsc.FIDSet
# only process layers/tables if there is a selection in the FCLyr
if len(selection_set) > 0:
print("{} has {} {}{} selected".format(FCLyr.name, len(selection_set.split(';')), 'feature' if '<geoprocessing Layer object' in strInsertFC else 'table row', '' if len(selection_set.split(';')) == 1 else 's'))
arcpy.AddMessage("{} has {} {}{} selected".format(FCLyr.name, len(selection_set.split(';')), 'feature' if '<geoprocessing Layer object' in strInsertFC else 'table row', '' if len(selection_set.split(';')) == 1 else 's'))
FCfields = arcpy.ListFields(FCLyr)
insertFCfields = arcpy.ListFields(insertFCLyr)
# Create a field list of fields you want to manipulate and not just copy
# All of these fields must be in the insertFC
manualFields = []
matchedFields = []
for manualField in manualFields:
matchedFields.append(manualField.upper())
for FCfield in FCfields:
for insertFCfield in insertFCfields:
if (FCfield.name.upper() == insertFCfield.name.upper() and
FCfield.type == insertFCfield.type and
FCfield.type <> 'Geometry' and
insertFCfield.editable == True and
not (FCfield.name.upper() in matchedFields)):
matchedFields.append(FCfield.name)
break
elif (FCfield.type == 'Geometry' and
FCfield.type == insertFCfield.type):
matchedFields.append("SHAPE@")
break
elif insertFCfield.type == "OID":
oid_name = insertFCfield.name
if len(matchedFields) > 0:
# Print the matched fields list
print("The matched fields are: {}".format(matchedFields))
arcpy.AddMessage("The matched fields are: {}".format(matchedFields))
copies = parameters[2].value
print("Making {} {} of each {}".format(copies, 'copy' if copies == 1 else 'copies', 'feature' if '<geoprocessing Layer object' in strInsertFC else 'table row'))
arcpy.AddMessage("Making {} {} of each {}".format(copies, 'copy' if copies == 1 else 'copies', 'feature' if '<geoprocessing Layer object' in strInsertFC else 'table row'))
oid_list = []
# arcpy.AddMessage(oid_name)
dscInsert = arcpy.Describe(insertFCLyr)
if '<geoprocessing Layer object' in strInsertFC:
oid_name = arcpy.AddFieldDelimiters(dscInsert.dataElement, oid_name)
else:
oid_name = arcpy.AddFieldDelimiters(dscInsert, oid_name)
rowInserter = arcpy.da.InsertCursor(insertFCLyr, matchedFields)
print("The output workspace is {}".format(insertFCLyr.workspacePath))
arcpy.AddMessage("The output workspace is {}".format(insertFCLyr.workspacePath))
if '<geoprocessing Layer object' in strInsertFC:
versioned = dscInsert.featureclass.isVersioned
else:
versioned = dscInsert.table.isVersioned
if versioned:
print("The output workspace is versioned")
arcpy.AddMessage("The output workspace is versioned")
with arcpy.da.Editor(insertFCLyr.workspacePath) as edit:
with arcpy.da.SearchCursor(FCLyr, matchedFields) as rows:
for row in rows:
for i in range(copies):
oid_list.append(rowInserter.insertRow(row))
else:
print("The output workspace is not versioned")
arcpy.AddMessage("The output workspace is not versioned")
with arcpy.da.SearchCursor(FCLyr, matchedFields) as rows:
for row in rows:
for i in range(copies):
oid_list.append(rowInserter.insertRow(row))
del row
del rows
del rowInserter
if len(oid_list) == 1:
whereclause = oid_name + ' = ' + str(oid_list[0])
elif len(oid_list) > 1:
whereclause = oid_name + ' IN (' + ','.join(map(str, oid_list)) + ')'
if len(oid_list) > 0:
# arcpy.AddMessage(whereclause)
# Switch feature selection
arcpy.SelectLayerByAttribute_management(FCLyr, "CLEAR_SELECTION", "")
arcpy.SelectLayerByAttribute_management(insertFCLyr, "NEW_SELECTION", whereclause)
print("Successfully inserted {} {}{} into {}".format(len(oid_list), 'feature' if '<geoprocessing Layer object' in strInsertFC else 'table row', '' if len(selection_set.split(';')) == 1 else 's', insertFCLyr.name))
arcpy.AddMessage("Successfully inserted {} {}{} into {}".format(len(oid_list), 'feature' if '<geoprocessing Layer object' in strInsertFC else 'table row', '' if len(selection_set.split(';')) == 1 else 's', insertFCLyr.name))
else:
print("Input and Output have no matching fields")
arcpy.AddMessage("Input and Output have no matching fields")
else:
print("There are no features selected")
arcpy.AddMessage("There are no features selected")
# report if a layer/table cannot be found
if FCLyr == None:
print("There is no layer or table named '{}' in the map".format(FC))
arcpy.AddMessage("There is no layer or table named '" + FC + "'")
if insertFCLyr == None:
print("There is no layer or table named '{}' in the map".format(insertFC))
arcpy.AddMessage("There is no layer or table named '{}' in the map".format(insertFC))
arcpy.RefreshActiveView()
return
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)
... View more
07-08-2015
02:29 PM
|
0
|
0
|
2905
|
| Title | Kudos | Posted |
|---|---|---|
| 1 | 03-24-2026 11:37 PM | |
| 1 | 03-24-2026 08:01 PM | |
| 7 | 02-23-2026 08:34 AM | |
| 1 | 03-31-2025 03:25 PM | |
| 1 | 03-28-2025 06:54 PM |
| Online Status |
Offline
|
| Date Last Visited |
2 weeks ago
|