Is there a way to show the attribute table of selected features using arcpy? Maybe in the mapping module?
I would like to be able to select some features and then have an Add-In button that displays the attribute table for just the selected features.
I understand that this seems rudimentary for GIS people, but I'm trying to meet the needs of a specific request for work.
I'm able to do this now using tkinter and only showing the needed attributes, but it's a bit messy and isn't stable. I know, The stability issue is a known issue with using tkinter in parallel with ArcGIS. So... I'm hoping I can just bring up the attribute table in an automated "neat little button with the company logo on it" way.
-
1Because you're wanting to interact with the application, you will probably have to approach this using ArcObjects. And poking around a bit, it seems possible.evv_gis– evv_gis2015年01月21日 15:00:18 +00:00Commented Jan 21, 2015 at 15:00
-
Ugh... I was afraid of that. So... What do I need to get started? Download the SDK for .net and Visual Studio?GeoJohn– GeoJohn2015年01月21日 15:01:41 +00:00Commented Jan 21, 2015 at 15:01
-
2I'm not the best resource for ArcObjects info, but my only suggestion would be to look at the Getting Started guide on the Resource Centerevv_gis– evv_gis2015年01月21日 15:03:32 +00:00Commented Jan 21, 2015 at 15:03
-
1Would it be possible to use arcpy to grab the selected features and write them to a a csv or excel file? From there you can launch the features in excel, or even have them save it to disk somewhere.jOshT– jOshT2015年01月21日 21:04:03 +00:00Commented Jan 21, 2015 at 21:04
-
@jOshT That approach is something I could easily handle and have done before. Unfortunately, the ideal scenario would be to allow the user to simply click a button and have the data displayed directly from ArcMap.GeoJohn– GeoJohn2015年01月22日 18:57:26 +00:00Commented Jan 22, 2015 at 18:57
1 Answer 1
I'm not sure about how to do this in Python other than using ArcObjects directly through COM interop - hardly the most pleasant approach. It's much easier to do in .NET, though for simplicity you will want the SDK and that's not available for download - I believe it comes with ArcGIS Desktop install media? And definitely with an EDN licence, of course, but hopefully a basic Desktop licence will include it.
To do this in .NET, you'll need to create an Add-In with a Button. Within the button you'll need to get the selected features and the layers containing them, then create a TableWindow, assign it the layer and application, and show the window. It's about 60 lines of code to write after generating everything else from the ESRI templates. If you don't have the SDK, you can still do this but I think Add-In development needs the SDK so you'd have to go the ArcObjects extension route (extending ICommand etc) without any of the templates to help.
If you can go the Add-In route, the following code will open the attribute table for all layers in the map that have selections and configure them all to show only their selection when calling ShowTableWindowForAllSelected():
private IEnumerable<IFeatureClass> GetFeatureClassesWithSelectedFeatures()
{
IEnumFeature selection = ArcMap.Document.ActiveView.FocusMap.FeatureSelection as IEnumFeature;
selection.Reset();
IFeature feature;
List<IFeatureClass> classes = new List<IFeatureClass>();
while((feature = selection.Next()) != null)
{
IFeatureClass fClass = feature.Class as IFeatureClass;
if(fClass != null && !classes.Contains(fClass))
{
classes.Add(fClass);
}
}
return classes;
}
private IEnumerable<IFeatureLayer> GetFeatureLayersWithSelectedFeatures()
{
//get an enumerator for just feature layers
UID uid = new UIDClass();
uid.Value = typeof(IFeatureLayer).GUID.ToString("B");
IEnumLayer layerEnum = ArcMap.Document.ActiveView.FocusMap.get_Layers(uid: uid);
//load them into a dictionary w/ their feature class
layerEnum.Reset();
ILayer layer;
Dictionary<IFeatureLayer, IFeatureClass> layers = new Dictionary<IFeatureLayer, IFeatureClass>();
while((layer = layerEnum.Next()) != null)
{
IFeatureLayer fLayer = (IFeatureLayer)layer;
layers.Add(fLayer, fLayer.FeatureClass);
}
//get feature classes with selected features and join to the feature layers in the map
IEnumerable<IFeatureClass> fClasses = GetFeatureClassesWithSelectedFeatures();
IEnumerable<IFeatureLayer> layersWithSelectedFeatures =
layers.Join(fClasses,
layerEntry => layerEntry.Value,
fClass => fClass,
(layerEntry, fClass) => layerEntry.Key).Distinct()
return layersWithSelectedFeatures;
}
private void ShowTableWindowForAllSelected()
{
ITableWindow2 attrWindow = null;
//ITableWindow2 windowFinder = new TableWindowClass();
IEnumerable<IFeatureLayer> layers = GetFeatureLayersWithSelectedFeatures();
foreach(IFeatureLayer layer in layers)
{
//attrWindow = windowFinder.FindViaLayer(layer);
if(foundWindow == null)
{
foundWindow = new TableWindowClass();
foundWindow.Layer = layer;
foundWindow.Application = ArcMap.Application;
foundWindow.TableSelectionAction = esriTableSelectionActions.esriSelectFeatures;
foundWindow.ShowAliasNamesInColumnHeadings = true;
}
if(!foundWindow.IsVisible) foundWindow.Show(true);
//this seems to need to be done after the window is visible or it behaves a little strangely
foundWindow.ShowSelected = true;
}
}
If you want to use existing attribute windows instead of opening new ones each time the button is pressed, uncomment the two lines using 'windowFinder'.
-
1Great answer! As a side note for others who are wanting to start using ArcObjects, I was able to download the .net SDK through my account on arcgis.com. This of course, is due to the fact the my company has an active subscription. SO... just FYI, you don't necessarily need the install disk to get it. I will mark as accepted when/if I get this to work.GeoJohn– GeoJohn2015年01月22日 19:06:50 +00:00Commented Jan 22, 2015 at 19:06