ArcTool: simulating 'Use selected features' option

656
5
Jump to solution
04-03-2013 10:38 AM
StevePeaslee
Occasional Contributor
I have an ArcTool that runs a Python script. One thing I've always liked about out-of-the-box tools in ArcMap is that they often have the 'Use Selected Features' checkbox. If nothing else they warn the user that the process may only be applied to part of the layer instead of the entire thing.

This checkbox needs to be enabled when the input is a featurelayer. The box is automatically checked when there is already a selection on that layer. If the layer is a featureclass, then the checkbox is disabled.

I've tried programming that into the Tool Validation class and it sort of works, but using GetCount to compare the featurelayer recordcount to the featureclass record count is way too slow for large datasets. This causes the tool to 'hang' for quite a while.

I really don't care how many records are selected, just if there is a selection- True or False. Does anybody have a suggestion for quickly finding out if a selection has been applied? I'm hoping there's a layer property in arcpy.mapping that might work, but I don't see anything obvious.


-Steve
0 Kudos
1 Solution

Accepted Solutions
DaleHoneycutt
Occasional Contributor III
If the input is a Feature Layer (and probably a Table View as well), you can determine whether it has selected records using the FIDSet property of the describe object.  Here is some tests I made in the Python Window on a layer named "VennDiagram_1").  Note--for a dataset, the FIDSet property is not supported... you can only use this method with layers.
>>> # no selected records >>> d = arcpy.Describe("VennDiagram_1") >>> print d.FIDSet  >>> print len(d.FIDSet) 0 >>> # I select two features  >>> print d.FIDSet 7; 9 >>> # I clear the selection >>> print d.FIDSet  >>> # I select all records (note that this is the same as selecting none... in ArcMap/geoprocessing,  >>> #  nothing selected means to process all features. ) >>> print d.FIDSet 4; 6; 7; 8; 9; 12 >>> 

View solution in original post

0 Kudos
5 Replies
JoelCalhoun
New Contributor III
From what I've read is that if you use a script tool or I'm assuming a python add-in within ArcMap, it will automatically honor your selected set.  I'm not sure of the best way to determine if there is a selection but one thought is that you could run a couple of search cursors.  The first one will give you the number of records in the input layer or if there is a selection, just the number of selected records.  The second would be on the Feature Class.  Compare the two counts.  If the layer has less then you know you have selected records.

Completely untested but maybe something like this:
import arcpy

# SET THE LAYER
lyr = "Parcel_Poly"

# SET THE FEATURE CLASS
fc = "C:\\parcels.gdb\\parcels"

# SEARCH THE LAYER
lyr_rows = arcpy.da.SearchCursor(lyr, "PIN")
lyr_Count = 0
for lyr_row in lyr_rows:
    lyr_Count += 1
del lyr_row, lyr_rows

# SEARCH THE FC
fc_rows = arcpy.da.SearchCursor(fc, "PIN")
fc_Count = 0
for fc_row in fc_rows:
    fc_Count += 1
del fc_row, fc_rows

if lyr_Count == fc_Count:
    #Do Something
0 Kudos
DaleHoneycutt
Occasional Contributor III
If the input is a Feature Layer (and probably a Table View as well), you can determine whether it has selected records using the FIDSet property of the describe object.  Here is some tests I made in the Python Window on a layer named "VennDiagram_1").  Note--for a dataset, the FIDSet property is not supported... you can only use this method with layers.
>>> # no selected records >>> d = arcpy.Describe("VennDiagram_1") >>> print d.FIDSet  >>> print len(d.FIDSet) 0 >>> # I select two features  >>> print d.FIDSet 7; 9 >>> # I clear the selection >>> print d.FIDSet  >>> # I select all records (note that this is the same as selecting none... in ArcMap/geoprocessing,  >>> #  nothing selected means to process all features. ) >>> print d.FIDSet 4; 6; 7; 8; 9; 12 >>> 
0 Kudos
StevePeaslee
Occasional Contributor
dmhoneycutt,

Thanks.

I tried the FIDSet method and got some interesting results using ArcGIS 10.0.

When FIDSet was used to get a count for the selected set, it worked really fast when compared to GetCount. For some reason I was unable to get FIDSet to work against a featurelayer containing the entire featureclass (3.3 million records). I was getting back an empty string. Not at at all what I was expecting. There must be something wrong with GetCount in ArcGIS 10.0.

I decided to try GetCount one more time, just to get the total number in the featureclass and surprisingly it worked fine.

So for now I am using a combination of FIDSet to get the number selected and GetCount for the total number of features in the featureclass. It turns out that my original slow performance was completely due to using GetCount on the featurelayer.

I wasn't able try the da cursor since my ArcTool has to be compatible with both 10.0 and 10.1. Thanks anyway for the suggestion.
0 Kudos
curtvprice
MVP Esteemed Contributor
There must be something wrong with GetCount in ArcGIS 10.0.


I haven't had any problems with GetCount myself. Are you sure you're using it properly - it now returns a result object instead of a string:

Arc 9.3:
number = int(gp.GetCount_management("mylayer"))


Arc 10.x:
Result = arcpy.GetCount_management("my layer")
number = int(Result.getOutput(0)) 
0 Kudos
JoelCalhoun
New Contributor III
Dale, thanks for the info on the FIDSet, it was most helpful.

Steve, I think what Dale has provided makes testing the Feature Class itself unnecessary.

If len(d.FIDSet) > 0 then you have selected records.

Also using this you can find the number of selected records.

Something like this:

import arcpy

# Import strftime from time module
from time import strftime

lyr = "Parcels_Layer"

# MESSAGES FUNCTION
def messages(message):
    arcpy.AddMessage(strftime("%m-%d-%Y %I:%M:%S %p ") + str(message))
    print(strftime("%m-%d-%Y %I:%M:%S %p ") + str(message))

d = arcpy.Describe(lyr)
if len(d.FIDSet) > 0:
    Feat_Sel_List = d.FIDSet.split(";")
    messages(len(Feat_Sel_List))
0 Kudos