POST
|
I have come across a task that appears to need a Python add-in. Searching the internet for reference books, guides, training materials, for how to develop one of these things - I come up dry. I've downloaded and 'installed' the "Python Add-in Wizard" and run 'addin_assistant.exe' to create the stub for the tool. But obviously it appears to need a lot more work than just that. Any information on what I need to be doing in the dialog box for the addin_assistant ? What are the functions? how do they relate to the addin_assistant? Are there really no thorough materials out there describing how this system works? How one goes from zero to a working python add-in?? A general outline of the tool is: user clicks on a point in the map, the tool searches an external database to find what information is available at that point, shows a list to the user, user selects one or more items, when are then loaded into the map as layers. Apparently, the OnMapClick function/method is what I need here to get this working. But knowing that doesn't tell me how to use the python add-in development tools. platform: ArcGIS 10.4 - 10.6 on Windows 10 (this comes with the ArcGIS install of Python 2.7.10)
... View more
04-18-2019
02:53 PM
|
0
|
3
|
597
|
POST
|
Seems a simple question: My python tool is looping through records and outputting a "<current record> being processed" message in the tool's running dialog box. As the tool loops through the <records> it's generating some output file (in this case an excel file). I'm using the SetProgressor/SetProgressorPosition feature of arcpy to show progress through the loop. But now my users understandably want to be able to click on the 'Cancel' button in the upper right corner of the dialog box and have the tool stop running, but still save the results of the <records> that were processed. This site (arcpy - Forcing Python Toolbox tool to break loop and do cleanup when user clicks Cancel? - Geographic Information Syste… ) claims that you can wrap the arcpy.SetProgressorPosition() call in a try/except construct and that the except clause gets executed if the user has clicked on the Cancel button. (I'm running ArcGIS Desktop 10.4.1 in Windows 10) I do not finding the above technique to work. How does an arcpy script capture the user clicking on 'Cancel' and having a chance to clean-up before exiting?
... View more
11-02-2018
05:19 PM
|
0
|
2
|
870
|
POST
|
Taking this another step then ... I was trying to make interactive debugging possible while developing an arcpy tool. (interspersing my code with bits of arcpy.AddMessage() to output variable values is so ... 1970's; i.e. lame.) It is apparently well known that running the python debugging IDE takes you away from the current map document in which the tool is invoked. I.e., references to layers by only their name works fine if the current map document is available but not when debugging because there is no 'current map document' available. Is there some mysterious undocumented 'environment'-like value that indicates what the current map document is? If I could set this, then references to layers by namestring could work. But I can't find a way to set this. I was hoping that if a tool says it takes a 'layer' as input, that it really meant a layer object and that object could refer to a layer in the current map document or a layer object obtained from an 'external' map document. But arcpy tools that take layer names apparently only search for those names in the 'current' map document; and when I'm in the interactive debugger then there is no current map document. This is dumb. Why can't I just set the current map document and get a working context during debugging??
... View more
02-07-2018
11:57 AM
|
0
|
0
|
1329
|
POST
|
OK... a closer reading of the online documentation for tabulateIntersection states that if the Zone and the Class features are the same dimension (e.g. both polygons) then the value for PERCENTAGE computed is the percentage of the Zone feature, but that if the Zone and Class features are different dimensions (e.g. Zones are lines, Classes are polygons) then the value for PERCENTAGE computed is the percentage of the Class feature. Perhaps there's a reason for this design, or perhaps it's just a result of the way the tool is coded.
... View more
12-19-2017
05:01 PM
|
2
|
1
|
664
|
POST
|
Tabulate intersection for different geometries produces inconsistent outputs. I have class features in layers of point, line and polygon geometries. I'm using TabulateIntersection_analysis to to determine the portion of each class feature that is in a county (using a polygon layer of county boundaries). So, the Zone layer has to be the county boundaries layer, and each analysis uses a different tabulating class layer (point, line, poly) across those counties. For points, the output makes sense, the results contain 2 columns: "PNT_COUNT" and "PERCENTAGE". For these points, the value in PERCENTAGE contains the percentage of the class' points that are in that county. For a given Class Field value, the total percentages add up to 100%, and the number of points add up to the total number of points for the given class Field value. Likewise, for lines, the result contains "LENGTH" and "PERCENTAGE" and the Percentage values for a given class field value add up to 100%. BUT.. when the class layer is a polygon, the outputs are "AREA" and "PERCENTAGE" but the values for PERCENTAGE represent percent of Zone, not percent of that class field value in that county. This is, effectively, the opposite of the results for the line and point geometry class layer outputs. I realize that by swapping Zone and Class parameters for polygon-only features, I get what I want, but I now have to write code to detect the class feature's geometry type and call tabulateIntersection_analysis with differently arranged parameters depending on the class feature's geometry. Surely, something isn't working the way it's intended!?!? Context: ArcGIS Desktop 10.4.1 Python (arcpy) Windows 7
... View more
12-19-2017
11:25 AM
|
0
|
2
|
1565
|
POST
|
I find this confusion over what seem to be various flavors of 'Layer' objects. Once you get arcpy to hand you a layer object from ListLayers and you loop through them, try using the name property of the lyr instead of the layer object itself. E.g.: this seems to work for me: arcpy.SelectLayerByAttribute_management(lyr.name, "CLEAR_SELECTION") And, as many others note, this is really slow. And if going to ArcObjects is not in your game, there is a python code through arcpy that clears selections really fast: lyr.setSelectionSet("NEW",[]) Note: this is calling a method of the layer object, it is not an arcpy function.
... View more
10-05-2017
12:05 PM
|
0
|
0
|
622
|
POST
|
I don't understand when an input argument to an arcpy function that says it takes a layer as an input but it really only works when I give it the name of the layer. Specifically: I use the arcpy.mapping.ListLayers() function to get a list of all the 'layers' in my mxd. I then search through this list to find the layer for which the .name value of the layer I'm interested in. I then copy this layer object out of the list returned by ListLayers(). I assume that what I have is a layer in the sense of what's documented on this page: Layer—Help | ArcGIS Desktop I then read the documentation for the SelectLayerByAttribute_management() at: Select Layer By Attribute—Help | ArcGIS Desktop and it looks like it says that it takes a 'Layer' as it's first argument. So I call arcpy.SelectLayerByAttribute_management() handing it my layer object (from above) and the second argument of "CLEAR_SELECTIONS". The error message I get back is "ERROR 000732: Layer Name or Table View: Dataset GPL0 does not exist or is not supported". so, it seems I just called a function that wants a layer as its first argument and I hand it a layer object that arcpy handed to me, and the function barks. So I try using the string value of the layer name as the first argument and now the function works like a charm! So, if a string value of the layer's name that I want to clear selections for is what the function wants, then why doesn't the documentation say the the first argument is a string value, instead of a layer object? Python snippet: mxd = arcpy.mapping.MapDocument("CURRENT") main_frames = arcpy.mapping.ListDataFrames(mxd,"Layers") main_frame = main_frames[0] main_layers = layers = arcpy.mapping.ListLayers(mxd,"*",main_frame) for lay in main_layers: if lay.name == 'Report Polygons': rpolys = lay rpolys.isFeatureLayer # this is 'True' rpolys.isBroken # this is 'False' rpolys.isGroupLayer # this is 'False' rpolys.serviceProperties['Is_Geodatabase'] # this has the value 'true' arcpy.SelectLayerByAttribute_management(rpolys,"CLEAR_SELECTION") # this fails arcpy.SelectLayerByAttribute_management(rpolys.name,"CLEAR_SELECTION") # this gives me a <Result> This seems to be the case for many of the arcpy functions that claim to take a 'Layer' as an input argument - all they really want is a string that contains the name of the layer. Is it a fools errand to search my mxd for the layer I want to use when it appears that functions like SelectLayerByAttribute_management() will do it for me?
... View more
10-05-2017
11:46 AM
|
1
|
3
|
3006
|
POST
|
We have a polyline feature class (in our enterprise sql geodatabase) with a couple attributes that have domains specified. During the usual manual editing of features, it works like a charm - users can only select one of the defined values in the attribute's domain. But the Field Calculator allows any (string) value to be placed in the field, including string values that are neither a domain code nor domain description. I get the same problem in Python code using arcpy.UpdateCursor. If somebody starts an edit session, enters invalid attribute values (i.e. non-domain) into ~200 features and then saves the edits and walks away - ArcGIS doesn't even blink an eye. I have to start up the editor again, select those ~200 features (in my case, across 5 feature classes) and then run "Validate Features" to have ArcMap bark at me about "Field xxx attribute value yyy is not a member of coded value domain zzz". Rather defeats the purpose of using a domained attribute. What do others do?
... View more
03-23-2017
04:24 PM
|
2
|
5
|
1580
|
POST
|
Curtis' suggestion worked. I don't have the time to dig out the differences in the 2 user profiles to see what could cause the different outcomes.
... View more
10-14-2015
04:48 PM
|
0
|
0
|
376
|
POST
|
You are correct. It is a copy/paste issue. The widget for pasting in python code doesn't seem to work smoothly for 93 lines of code. I inadvertently deleted the 'd'. The 'd' is there in the code on my machine.
... View more
10-06-2015
12:12 PM
|
0
|
2
|
376
|
POST
|
Ok. 2 things... 1) I've been able to try out the example code (without Curtis' suggestion implemented) on the user's 10.1 station, logged in as them. It crashes on the MakeFeatureLayer_management at the end (line 85). So, whatever I'm stumbling across seems to be affected by the user profile, not the version of ArcGIS. 2) I switched over the code to Curtis' suggestion and it works as advertised. But the name of the layer shows up in the TOC as "example_results", not the name I want it to have (e.g. "Your Results") - which would be based on the user's inputs. I suppose I can work around this by making the name of the destination_feature_class to be name of the layer as I want it to appear in the TOC. I don't understand fully what is intended by the semantic: "(Your results", Derived, type Feature Class)". Here is how I setup the 4th parameter in the tool's properties box: As for environments being local - I confess I find the issues of namespaces and execution scoping to be a snake pit, so I just play it safe and save and restore values.
... View more
10-06-2015
11:14 AM
|
0
|
5
|
376
|
POST
|
Let me say more about this... I've reduced the code down to show the basic process, without making it too simplified. In this reduced example code, I've ripped out all the code that uses a couple other Python modules that are in the actual production code: pymssql (to pull data from our SQL server database), and openpyxl (to update an excel spreadsheet with more data about the results of the code running). Also gutted out is code that detects if data from a previous run of the tool exists, in which case it deletes it before continuing on to to the actual processing. Herewith: import arcpy
import os
import getpass
# save the current workspace
save_workspace = arcpy.env.workspace
# get the current user's login id
run_user = getpass.getuser()
# get 3 parameter values
ex_district = int(arcpy.GetParameterAsText(0))
ex_year = int(arcpy.GetParameterAsText(1))
ex_num = int(arcpy.GetParameterAsText(2))
# this is where the 'raw' data is coming from
data_source = r"N:\gis-files\merged.gdb\raw"
# this where the prepared data is going to
destination_gdb_directory = r"N:\shared\George"
destination_gdb_name = "ex_gdb.gdb"
arcpy.CreateFileGDB_management(destination_gdb_directory,destination_gdb_name)
# set the workspace to this destination GDB
arcpy.env.workspace = os.path.join(destination_gdb_directory,destination_gdb_name)
# create a new feature class in the destination GDB
estination_feature_class = "example_results"
destination_feature_template = r"MAIN\Reports\Reports (polygons)"
arcpy.CreateFeatureclass_management(arcpy.env.workspace,destination_feature_class,"POLYGON",destination_feature_template,"SAME_AS_TEMPLATE","SAME_AS_TEMPLATE",destination_feature_template)
# create some kind of 'layer' that is a selection of the 'raw' data
ex_where = "(REGION={0} AND YEAR={1} AND NUM={2})".format(ex_district,ex_year,ex_num)
ex_data_select = "example_data_select"
arcpy.MakeFeatureLayer_management(data_source,ex_data_select,ex_where)
# copy the selected features out of the 'raw' data
ex_data_copied = "example_data_copied"
arcpy.CopyFeatures_management(ex_data_select,ex_data_copied)
# dissolve them into 1 feature
ex_data_dissolved = "example_data_dissolved"
arcpy.Dissolve_management(ex_data_copied,ex_data_dissolved,"","","MULTI_PART")
# cut that feature up by county boundary
ex_data_intersected = "example_data_intersected"
ex_intersect_inputs = [ex_data_dissolved, 'Basemap\\County outlines']
arcpy.Intersect_analysis(ex_intersect_inputs,ex_data_intersected,"ALL", "", "INPUT")
# add features to the prepared data with our attributes
from_shape_field = arcpy.Describe(ex_data_intersected).ShapeFieldName
to_shape_field = arcpy.Describe(destination_feature_class).ShapeFieldName
copy_from = arcpy.SearchCursor(ex_data_intersected)
insert_to = arcpy.InsertCursor(destination_feature_class)
for from_row in copy_from:
new_row = insert_to.newRow() # create empty record
new_row.setValue(to_shape_field,from_row.getValue(from_shape_field)) # copy geometry
new_row.setValue('DocNo',ex_num) # put in source document number
new_row.setValue('OtherID',from_row.getValue('NAME')) # copy county name
new_row.setValue('DigBy',getpass.getuser()) # put in user name
insert_to.insertRow(new_row) # add feature to final destination
del new_row
del copy_from
del insert_to
# load the destination_feature_class into the user's map TOC
new_map_layer = "Your Results"
arcpy.MakeFeatureLayer_management(destination_feature_class,new_map_layer)
this_mxd = arcpy.mapping.MapDocument("CURRENT")
this_frame = arcpy.mapping.ListDataFrames(this_mxd)[0]
this_layer = arcpy.mapping.Layer(new_map_layer)
arcpy.mapping.AddLayer(this_frame,this_layer,"TOP")
# restore the prior workspace
arcpy.env.workspace = save_workspace (let me know if the Python code snippet didn't paste in correctly above) This is run as a script tool in a 'plain' toolbox (not a 'Python toolbox'). On my 10.2 installation it works like a charm. The only layer that gets added to my map is the one at the end and it shows up at the top of the TOC as 'Your Results'. And it contains the correct data. Yay! Now... for the interesting part ... I log in, as me, on a different machine that's installed with 10.1 and I run this tool and it also works as expected. Grnpph. So... either: 1) in simplifying the code for example/discussion purposes I inadvertently fixed the problem or removed problem-causing code; or 2) something about the profile of the usual user is causing it to bomb out. The usual user of this tool has left for the day and I can't log in as them to try it out under their login today. I'll try it out with them the next time they're in and available.
... View more
10-05-2015
06:41 PM
|
0
|
7
|
376
|
POST
|
The code is running as a script tool in a 'regular' toolbox. Not in a 'Python toolbox'.
... View more
10-02-2015
10:07 AM
|
0
|
2
|
789
|
POST
|
Hmmm... how to make sense of this question... I'm guessing that you're referring to the "Add results of geoprocessing operations to the display" that is a check box on the Geoprocessing Options dialog box. There is no comparable setting in the "Map Document Properties" dialog box that I can see. Furthermore, "Geoprocesing Options" are not a property of a map document (.mxd), but are application/user settings. (I can demonstrate this to myself by using 2 separate .mxd documents (map documents) and turning off "Add results of geoprocessing..." while in one map document, closing that map document (without saving), opening a different .mxd and seeing that the geoprocessing option is now turned off; and likewise for turning it on.) Our default installation is that "Add results of geoprocessing..." is turned on for every user/machine installation. And, it would surprise me *very* much if our users were sophisticated enough to go fiddling with the Geoprocessing Options. Turning that off or on is completely unnecessary for our workflow. Notwithstanding, I did check my 10.2 installation (where I developed the Python script) and I checked the user's 10.1 installation (where the script was used) and both had "Add results of geoprocessing ...." checked on. And, just in case you think to ask, the python script does not make any reference to the arcpy.env.addOutputsToMap setting (i.e. it neither reads it nor sets it).
... View more
10-01-2015
11:35 AM
|
0
|
4
|
789
|
POST
|
I have Python code that creates a file geodatabase on the user's local data directory, creates some features in the .gdb (involves copying features, merging, intersecting, etc.) and results in a feature class in that local .gdb that I then want to add to the current map document, to show the results of all the Python/arcpy processing for the user that ran the tool. The issue is that in 10.2 arcpy.MakeFeatureLayer_management does not add my final feature class to the current map document's TOC, So I use arcpy.mapping.Layer to make a layer of my final product and then use arcpy.mapping.AddLayer to add the layer to the current map document. Works great. But then the tool gets run on a different user's machine that's running ArcMap 10.1 and MakeFeatureLayer_management barks with an error '000733' - output layer is same as input layer. So I remove the arcpy.mapping code and just let MakeFeatureLayer_management work with the single parameter and now my results get added to the current map's TOC! (this is all 32-bit python/geoprocessing) The on-line documentation for 10.1 and 10.2 for MakeFeatureLayer_management don't mention any difference in behavior concerning whether the dataset's layer gets added to the current map document.
... View more
09-30-2015
06:28 PM
|
0
|
19
|
6035
|
Title | Kudos | Posted |
---|---|---|
2 | 03-23-2017 04:24 PM | |
1 | 02-19-2020 01:17 PM | |
2 | 12-19-2017 05:01 PM | |
1 | 10-20-2014 10:35 AM | |
1 | 08-18-2014 03:36 PM |
Online Status |
Offline
|
Date Last Visited |
11-23-2023
12:19 AM
|