POST
|
I was listening to your further comments on this thread and decided to revisit this later in the day to test; I tested with 10.2.1 and was surprised to duplicate your error -- I used an updated script I'll include below; unfortunately there was an error with my line in the previous script (previous post above) attempting to reference a variable that hasn't been defined yet (outlayer, in the MakeFeatureLayer line): outlayer + str(i + 1) It now works for gdb fcs and was correct in directing you to try using fully qualified fc pathnames: import arcpy, os from arcpy import env env.overwriteOutput = True env.addOutputsToMap = True env.workspace = r"C:\Users\whitley-wayne\Documents\ArcGIS\Default.gdb" # the following line results in 000622 and 000628 failures on the 2nd iteration... #input1 = 'Export_Output' # so instead set your input var to a fully qualified pathname to your gdb source input1 = os.path.join(env.workspace, 'Export_Output') print '\nusing a fully-qualified pathname to the fc:\n{0}\n'.format(input1) # sample of 2 outputs, added to the map only for testing purposes outlayer1 = "TVA_Distributors_Layer" outlayer2 = "TVA_PSA_Zips_Layer" # if querying OID, make sure you're querying the correct one objID = arcpy.Describe(input1).OIDFieldName print 'using the true OID field name, {0}\n'.format(objID) for i in range(2): outlayer = 'outlayer{0}'.format(str(i + 1)) qry = '{0} = {1}'.format(objID, str(i + 1)) print 'this is the query: {0}'.format(qry) arcpy.MakeFeatureLayer_management(input1, outlayer, qry) print '...check the map for {0}\n'.format(outlayer) print 'done.' I think you were at least partially correct about the 'in-memory locking' issue (or however you described it), because if I use the name with the layer in the TOC, somehow Make Feature Layer doesn't seem to 'look' for the fc directly in the gdb -- what I mean by that is I think the in-memory pointer to the layer creates a 'lock' or at least blocks the 2nd iteration. I'll show you what I mean - if the line in the code is used as follows: input1 = 'Export_Output' ...then, the run (from the same code above with the fully qualified line of code commented out) prints feedback as follows - I get hit with the both the dreaded 000628 and 000622 errors: using the true OID field name, OBJECTID_1 this is the query: OBJECTID_1 = 1 ...check the map for outlayer1 this is the query: OBJECTID_1 = 2 Runtime error Traceback (most recent call last): File "<string>", line 26, in <module> File "C:\Program Files (x86)\ArcGIS\Desktop10.2\arcpy\arcpy\management.py", line 6043, in MakeFeatureLayer raise e ExecuteError: ERROR 000622: Failed to execute (Make Feature Layer). Parameters are not valid. ERROR 000628: Cannot set input into parameter in_features. ...alternately (this is the fix), if I run with the fully qualified pathname line (os.path.join etc etc), the execution is seamless, successfully completing through the 2nd iteration (as intended) with the printed feedback: using a fully-qualified pathname to the fc: C:\Users\whitley-wayne\Documents\ArcGIS\Default.gdb\Export_Output using the true OID field name, OBJECTID_1 this is the query: OBJECTID_1 = 1 ...check the map for outlayer1 this is the query: OBJECTID_1 = 2 ...check the map for outlayer2 done. Hope that's clear... Wayne PS - intriguing, your post #7, thank you for that feedback.
... View more
05-30-2014
02:53 PM
|
0
|
0
|
1527
|
POST
|
Haven't tested this, but think I see the source of your problem...you said: "I am entering in the code through the iterative python window, and both fcs are in the TOC, and neither Feature Layer exists prior to running the code." I'm sure you meant 'interactive python window'- regardless of that, you also said 'both fcs are in the TOC'. I think that's your problem. You would achieve more effective results using the fc reference to your workspace. Note that what you refer to as fcs in your TOC is actually what I've seen called a 'map layers' or at any rate are really just feature layers you can reference from the map. So your fix then is to use the statement you currently have commented out (if that gdb is actually where your input is): #env.workspace = r"C:\Users\iamurray\Desktop\Ray\Zip Code\ZipCodes.gdb" You can use the fc name (not the map layer name) directly in the Make Feature Layer line...so, in brief, something like this (I'll leave the testing to you - the following is simply test code to show successful execution for a 2nd iteration, and so on.):
import arcpy
from arcpy import env
env.overwriteOutput = True
env.addOutputsToMap = True
env.workspace = r"C:\Users\iamurray\Desktop\Ray\Zip Code\ZipCodes.gdb"
# set your input var to a sample input fc name in your source, ZipCodes.gdb
input1 = 'your gdb fc name here'
# sample of 2 outputs, added to the map only for testing purposes
outlayer1 = "TVA_Distributors_Layer"
outlayer2 = "TVA_PSA_Zips_Layer"
for i in range(2):
arcpy.MakeFeatureLayer_management(input1, outlayer + str(i + 1), 'OBJECTID = ' + str(count))
print '...check the map for {0}'.format(outlayer + str(i + 1))
print 'done.'
Just test code, so let me know if something doesn't work - don't forget to set the input1 variable to an fc name in your gdb (this is just a test, so initially it doesn't matter what it is) -- should result in 2 added outputs reflecting feature layers restricted (or in other words, filtered) by the OBJECTIDs 1 and 2. If you get both added to your map okay, then you should be able to extend this to your specific example, thereby fixing your error. Wayne
... View more
05-29-2014
05:51 PM
|
0
|
0
|
1527
|
POST
|
Well, sure, spoil all the fun and use the field calculator! Yeah, that looks fine...but look at it this way: now you have learned another option (probably a faster option) to use da cursor, and you don't need to open ArcMap, open the table, get to the field calculator, etc etc in order to execute a script. In a script you can also, when needed, insert messaging and such on more complex operations to monitor or even trap where things go wrong on certain records. When the field calculator fails, everything comes to a screeching halt.
... View more
05-27-2014
05:22 PM
|
0
|
0
|
790
|
POST
|
...a little late, but I think this will help below. Character encoding is interesting, although a full understanding of it on my part is a work in progress. So at the start I apologize for my limited explanation and limited facility in French as well. Basically, to cut to the chase, the 'raw' entry of your unicode character is not 'understood' by python in order to encode it properly...so of course when you try to get it back (as with a print statement), you typically get nonsense. With my standard output (stout) set as cp1252, I get: �?© If you prefix it with 'u' (to distinguish it from a possible non-unicode character), you should be in business with the declared utf-8 formatting. Not sure if you have the unicodedata module in your python version, but I think you'll get the idea just reading the script and corresponding output (output included further below). Try this short demo (my system is different from yours, so also attached is the script for you to run on your own system):
# -*- coding: utf-8 -*-
import sys, unicodedata
print 'The default encoding is {0}'.format(sys.getdefaultencoding())
print 'The standard output encoding is {0}\n'.format(sys.stdout.encoding)
a= u"\xe9"
print 'Trial 1- variable \'a\' is:', a
print '...and this is the type: ', type(a)
print 'This character is {0}\n'.format(unicodedata.name(a))
a= u"é"
print 'Trial 2- variable \'a\' is:', a
print '...and this is the type: ', type(a)
print 'This character is {0}\n\n'.format(unicodedata.name(a))
a= u"Wow caractères Unicode peuvent être difficiles à manipuler, ce qui avec le codage et le décodage en cours."
print 'Trial 3- (a bunch of French with accented characters):\n'
print a
print '\n...and this is the type: ', type(a)
a="é"
print '\n\nTrial 4- variable \'a\' is now becomes gibberish, improperly encoded utf-8:', a
print '...and this is the type: ', type(a)
On my system, I get back this (from the print statements):
>>>
The default encoding is ascii
The standard output encoding is cp1252
Trial 1- variable 'a' is: é
...and this is the type: <type 'unicode'>
This character is LATIN SMALL LETTER E WITH ACUTE
Trial 2- variable 'a' is: é
...and this is the type: <type 'unicode'>
This character is LATIN SMALL LETTER E WITH ACUTE
Trial 3- (a bunch of French with accented characters):
Wow caractères Unicode peuvent être difficiles à manipuler, ce qui avec le codage et le décodage en cours.
...and this is the type: <type 'unicode'>
Trial 4- variable 'a' is now becomes gibberish, improperly encoded utf-8: �?©
...and this is the type: <type 'str'>
>>>
-Wayne PS- By the way, if I feed in the French in trial 3 above and forget the 'u' prefix, this is the resulting feedback printed, which should now be no surprise:
Wow caract�?¨res Unicode peuvent �?ªtre difficiles �?* manipuler, ce qui avec le codage et le d�?©codage en cours.
... View more
05-24-2014
05:54 AM
|
0
|
0
|
820
|
POST
|
Walt, in order to better service your question, can you start a new thread? Rephrase your question and include more details: your system info (which version of ArcGIS, your OS and whether 32 or 64 bit) and if possible attach some sample data. And just to clarify, when you say you have an accdb table, this doesn't sound like data that is 'spatially enabled' - you can't use a geoprocessing operation such as 'clip' on just a table...but you can do something like join to something else already spatially enabled, maybe make some sort of selection, and clip the result to create an output that perhaps you can copy rows from in order to create just a table (no spatial attributes). However, lacking details, it isn't clear if you've established read-access to your accdb to begin with. ArcGIS can 'piggyback' on the Access db format and use geodatabases with the mdb file extension - but this isn't read/write in quite the same way (nor is it recommended) in Access as it is in ArcGIS. Do you indeed have an mdb geodatabase or is your source data created/maintained in Access? PS - Welcome to the forums!
... View more
05-23-2014
04:35 AM
|
0
|
0
|
567
|
POST
|
It's okay...I'm learning too and have to admit, you posed a good challenge. Point to you for hanging in there! No need to apologize - next time, please post all of your relevant code...no 'subset' that may confuse matters. Thanks, Wayne
... View more
05-20-2014
02:43 PM
|
0
|
0
|
574
|
POST
|
I'm sorry to say, although you may already realize this, what you state as your 'business logic' and your implementation attempt to accomplish said logic are not quite coherent. I suppose we can conclude you're still in the right place, as we are all still learning. Let me warp this conversation back to what I surmise is 'the center'. What you say you want to do is quite easy to accomplish - but I don't want to delve too far into the details of your 'other' business logic because I think it can be hinged or added to the logic 'framework', if you will, that I show here. Besides, it is simpler just to add to what code sample (involving a single combobox) I've already posted above - I'll repeat the code below and add-in (no pun intended) the button code....and offer a few pointers further below. import arcpy import pythonaddins class ButtonClass7(object): """Implementation for testNonEditCombo_addin.button (Button)""" def __init__(self): self.enabled = True self.checked = False def onClick(self): combobox.value = '' combobox.refresh() class ComboBoxClass1(object): """Implementation for testNonEditCombo_addin.combobox (ComboBox)""" def __init__(self): self.editable = True self.enabled = True # introducing global global staticVal self.newfunction() self.value = staticVal = self.items[0] def onSelChange(self, selection): # redefining global global staticVal self.value = staticVal = selection print 'selection: {0}'.format(selection) def onEditChange(self, text): pass def onFocus(self, focused): if focused: self.newfunction() def onEnter(self): self.value = staticVal print 'self.refresh...so did the refresh function fire?' self.refresh() def refresh(self): arcpy.RefreshActiveView() print 'refreshed...' def newfunction(self): self.mxd = arcpy.mapping.MapDocument('current') self.items = [lyr.name for lyr in arcpy.mapping.ListLayers(self.mxd)] So, just to add a few small explanations, here you go: - My logic doesn't really do anything but load existing layers from the map into the combobox 'list'; add your own logic to select and zoom, whatever you want, where applicable. - The only thing modified in the added button is the 'onClick' where you said you simply wanted to 'clear the selection' in the combobox. See my reference to the combobox, "testNonEditCombo_addin.combobox"? The object reference to that class is simply 'combobox'. - Then, using that obj ref, the command to clear the box to essentially a blank value is: combobox.value = '' - However, you need to refresh the combobox to show it, hence the next line which calls the already existing refresh function: combobox.refresh() - Notice that function in the combox class simply calls the familiar refresh active view command, arcpy.RefreshActiveView()... it is the timing of the refresh execution you're interested in, so that's why you need the function 'callable' immediately after you change the combobox value from the button class. Note that you don't need the RefreshActiveView() command at all to refresh the combobox; simply calling the function triggers the internal 'update' mechanism on the combobox (if no additional logic entered, then use 'pass'). The use of RefreshActiveView() here was just a point of good housekeeping to also refresh the view. - You can include, if you wish, your other business logic in the button class to actually clear all selected features in the map....but that is academic at this point, as I said you can add logic as needed. Understand? It's simple when you have a handle on it. (okay, that pun was intended) Enjoy, Wayne PS- By the way, you could even clear the list via the button with: combobox.items = [], although that really doesn't have any practical value -- I think you'd want to reload the list using a different query, etc., if that makes sense.
... View more
05-20-2014
02:07 PM
|
0
|
0
|
574
|
POST
|
I have a workaround that doesn't use the editable property, but instead simply 'resets' any entered value in the combobox back to the last valid value (from the drop-down list of course). This is my test combobox script, kept short and easy to read, follow, and implement - easily modified to work on a selected set of field values or whatever the case may be. To keep things very simple, I'm only using some feature layers in my map's TOC. Some print statements were left in, in case you wanted to 'watch' from ArcMap's Python window.
import arcpy
import pythonaddins
class ComboBoxClass1(object):
"""Implementation for testNonEditCombo_addin.combobox (ComboBox)"""
def __init__(self):
self.editable = True
self.enabled = True
# introducing global
global staticVal
self.newfunction()
self.value = staticVal = self.items[0]
def onSelChange(self, selection):
# redefining global
global staticVal
self.value = staticVal = selection
print 'selection: {0}'.format(selection)
def onEditChange(self, text):
# I toyed with this function but decided not to use it in this example.
pass
def onFocus(self, focused):
# if any layers are added/removed from the TOC, the list is refreshed.
if focused: self.newfunction()
def onEnter(self):
self.value = staticVal
print 'self.refresh...so did the refresh function fire?'
self.refresh()
def refresh(self):
arcpy.RefreshActiveView()
print 'refreshed...'
def newfunction(self):
self.mxd = arcpy.mapping.MapDocument('current')
self.items = [lyr.name for lyr in arcpy.mapping.ListLayers(self.mxd)]
Let me know if you have further questions. Wayne
... View more
05-19-2014
03:04 PM
|
0
|
0
|
574
|
POST
|
Interesting problem, and good practice for programming add-ins, I think... I said I'd report back if I had anything more in the way of a working solution. At this point, if you consider this a problem with more than 1 component [I agree with you; it's (1) get the order of selection of features and (2) code a designated field in that selection order with a user-specified range of values (a starting number and step interval, essentially)]. So far, I solved the 1st component, the assembling of the list of OIDs. Only test code, so I'm sure it could be done several different ways. For simplicity, this is a start - which I thought was important to more clearly state what I meant about global scope of a variable, managing the list values, and debugging...and I left many print messages in as they aided me in debugging:
import arcpy
import pythonaddins
orderBySelOIDs = list()
orderBySelOIDs.append('is it alive?')
class globalListClass(object):
def __init__(self):
self.enabled = True
print 'self aware?'
def onEditorSelectionChanged(self):
print 'onEditorSelectionChanged fired...'
FIDreturn = arcpy.Describe(someLayer).FIDSet.split(';')
if FIDreturn != ['']:
selOIDs = [int(OID) for OID in FIDreturn]
print 'currently selected oids: {0}'.format(str(selOIDs))
uniqueSel = set(selOIDs).difference(orderBySelOIDs)
while len(uniqueSel) != 0:
orderBySelOIDs.append(uniqueSel.pop())
print 'oid list in order selected: {0}'.format(str(orderBySelOIDs))
else:
print 'no features in selection (or selection has been cleared)'
print 'this executes also on starting Editor...'
print 'what does orderBySelOIDs contain?: {0}'.format(str(orderBySelOIDs))
del orderBySelOIDs[:]
print 'the ordered list has been reset (emptied): {0}'.format(str(orderBySelOIDs))
def openDocument(self):
getLayers = arcpy.mapping.ListLayers(arcpy.mapping.MapDocument('current'))
if len(getLayers) != 0:
global someLayer
someLayer = getLayers[0]
print 'openDocument fired, setting global layer: {0}'.format(someLayer.name)
This, for example, is some of my feedback (in ArcMap's Python window):
>>>
openDocument fired, setting global layer: clip500
>>>
onEditorSelectionChanged fired...
no features in selection (or selection has been cleared)
this executes also on starting Editor...
what does orderBySelOIDs contain?: ['is it alive?']
the ordered list has been reset (emptied): []
>>>
onEditorSelectionChanged fired...
currently selected oids: [3]
oid list in order selected: [3]
>>>
onEditorSelectionChanged fired...
currently selected oids: [1]
oid list in order selected: [3, 1]
>>>
onEditorSelectionChanged fired...
currently selected oids: [4]
oid list in order selected: [3, 1, 4]
>>>
onEditorSelectionChanged fired...
currently selected oids: [2]
oid list in order selected: [3, 1, 4, 2]
>>>
onEditorSelectionChanged fired...
no features in selection (or selection has been cleared)
this executes also on starting Editor...
what does orderBySelOIDs contain?: [3, 1, 4, 2]
the ordered list has been reset (emptied): []
I suppose a small bit of explanation is in order - just to include a few points: -- Again, for simplicity, I included only 3 functions - __init__(self), onEditorSelectionChanged(self), and openDocument(self). -- As part of initializing, getting a map layer was necessary - this was done with the openDocument(self) function, fetching the 1st layer in the map. This is where a global layer variable was set up (someLayer) so that it could be used 'outside' the scope of the immediate function (where it was created) -- it was created inside this function because I didn't want to re-create the layer reference every time onEditorSelectionChanged fires...I suppose onStartEditing(self) would have been a better choice. -- onEditorSelectionChanged is fired even just starting the edit session, so I chose to use the list to send myself a message which I'd change on occasion to make sure I'm running the currently installed code (the current version I assume I'm working on). This serves no useful purpose outside of debugging and I just left it in. -- FIDSet was used on Describe of the global layer (someLayer) instead of a cursor. This returns a semi-colon ( ; ) separated string of the selected feature OIDs. -- orderBySelOIDs holds the order of features selected by OID...upon clear selection (or no features targeted on a selection), the list is cleared -- not redefined since that introduces another scope problem, but emptied. Strangely, there's no 'clear' method on list objects (there is for 3.x I'm told), so I rather clumsily used the following (but it works and the list should be short, so not a great concern for efficiency): while len(orderBySelOIDs) != 0: orderBySelOIDs.pop() EDIT: Substituted the following line instead-- del orderBySelOIDs[:] -- This test script accepts either use of the Edit tool on the editing toolbar or the Select Features tool, just as you'd expect in the Editing environment --- also, handling is added for selection of multiple features at a time, but simply loads the list in the OID order, appending whatever remaining OIDs are not already in the list. So that's fairly basic handling of constructing a list of feature OIDs in the order of selected features during an edit session...the 2nd component of actually using the list and handling the field coding of sequential numbers, etc., remains. If I have time for that later, I'll take another stab at it...back-burner as you said for now, but glad to at least clarify part of this thread. My guess it's just a matter of reading the list from memory, to then pass to the logic of another add-in to accept user input and probably running an update cursor --- read perhaps a dictionary to look up position in the sequence and assign the field value.... Wayne
... View more
05-12-2014
04:04 PM
|
0
|
0
|
822
|
POST
|
Sorry for the misunderstanding - I really didn't mean that as part of the overall solution, only to point out the immediate source of the error message. More explicitly, this:
>>> aList = list()
>>> aList.append(1)
>>>
>>> # not allowed:
>>> aList(0)
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
aList(0)
TypeError: 'list' object is not callable
>>>
>>> # allowed:
>>> aList[0]
1
>>>
>>> # or:
>>> for item in aList:
print item
1
>>>
My 2nd point about the infinite loop was just that even if you didn't get that error, your loop that would have been entered would be a process you'd have to kill (unless the lists were identical), because the item is being added to your list so that the 'not in' logic would never evaluate false...if that now makes sense? Sorry for the confusion...if I have anything else to contribute later, it'll be more toward the overall solution, lol! Wayne Edit: This is important to see, about infinite loop situation:
>>> lstChanged = [1,2,3]
>>> lstDoubleCheck = [1,2]
>>>
>>> for item in lstChanged:
if item not in lstDoubleCheck: # error fixed here
lstChanged.append(item) # new error introduced here
if len(lstChanged) == 20: # for demo purposes, forced a break
break
>>> # so here's what we have:
>>> print lstChanged
[1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
>>> # the integer item '3' would have been appended infinitely.
... View more
05-08-2014
08:11 AM
|
0
|
0
|
822
|
POST
|
I have little to add, just was checking back on your progress... Be glad that line did error out because that's potentially an infinite loop - if you didn't already catch this (probably you have), I think you meant:
for item in lstChanged:
if item not in lstDoubleCheck:
lstDoubleCheck.append(item) # not lstChanged
I'm interested to see how this develops if you're still working on it, so I hope to get more time today to check back in... Thanks, Wayne
... View more
05-08-2014
04:05 AM
|
0
|
0
|
822
|
POST
|
Actually, I think it could be simpler than that - although I haven't had time to test this yet... I think the key may be to declare a global variable. Here's an example of passing a global layer var, see this posted by Jake Skinner: http://forums.arcgis.com/threads/99718-How-to-populate-Add-In-Combo-Box-with-attributes#2 Pay no mind to the 'onSelChange' function which only has to do with listening to the change in the combobox selected item... what I'm referring to is the ability to pass variables between functions - the onFocus function establishes the 'layer' obj which then can be referenced by SelectLayerByAttribute operation in the onSelChange function. In a similar way I don't see why not you can't initiate a global list variable that you can use to keep track of a the currently selected features and use to compare the 'new selection' via the onEditorSelectionChanged event. Like I said, haven't tested it, but the general concept is that onEditorSelectionChanged should be fired and you should be able to track the order of selected features in a global list. Hope that helps. Wayne
... View more
05-06-2014
11:53 AM
|
0
|
0
|
822
|
POST
|
...interesting. If I haven't oversimplified, if sounds to me that you need to listen for the selection change, keep track of a list that records the OIDs then list them in that noted order in a form to fill in the lot numbers? Otherwise, I think (if you need to maintain the selection set), you'd need to 'remember' in some way what's in the set before the selection changed, compare the 'before' and 'after' state of all the OIDs to get the added OID - in this way, you'd be doing this for every single feature selection (in other words, on selection change). So, an extension of this idea to apply it to your add-in: http://gis.stackexchange.com/questions/44733/how-to-get-list-of-selected-features-in-arcgis-for-desktop-using-python-code?rq=1 Hope that helps clarify a little... if not, then I'm off-track and let me know. Wayne EDIT: I suppose to support my reasoning, and this is efficient enough for say a dozen features or so that you want to code lot numbers for at a time, then comparing 2 lists for the added selected OID, maybe something this (there may be a much simpler means, maybe difference of the 2 sets?):
>>> # state at one point of the selection
>>> listOfOIDs1 = [1,2,3,4]
>>> # state after adding to the selection (5 added)
>>> listOfOIDs2 = [1,2,3,4,5]
>>> theNewOID = [oid for oid in listOfOIDs2 if oid not in listOfOIDs1]
>>> print theNewOID
[5]
>>>
>>> # EDIT 2:18 PM
>>> # ...or this, to compare lists:
>>> set(listOfOIDs2).difference(listOfOIDs1).pop()
5
... View more
05-06-2014
09:47 AM
|
0
|
0
|
822
|
POST
|
Nice Chris!- and incidentally (if I'm not mistaken), the 'distance' lines can be shortened to use the hypot function... In other words:
distance1 = math.sqrt((x1 - x2)**2 + (y1 - y2)**2)
...is equivalently:
distance1 = math.hypot((x1 - x2), (y1 - y2))
Wayne
... View more
05-06-2014
08:47 AM
|
0
|
0
|
3025
|
Title | Kudos | Posted |
---|---|---|
1 | 01-09-2013 07:16 AM | |
1 | 12-09-2013 08:44 AM | |
1 | 11-21-2013 07:35 AM | |
1 | 10-31-2012 08:28 AM | |
1 | 12-06-2012 07:44 AM |
Online Status |
Offline
|
Date Last Visited |
11-11-2020
02:23 AM
|