Here is a Python tool to hide selected features in ArcMap and to bring them back to screen. Useful if you need to create a screenshot / printout but want to hide certain features but not a whole layer. The tool applies a definition filter to "hide" selected features (across multiple layers) and removes the filters to display the features again. Filter condition is added to existing query.
Initial idea found on gis.stackexchange:
https://gis.stackexchange.com/questions/368848/creating-definition-query-from-selected-features-using-arcgis-pro
First the toolbox definition - save as PYT file:
# -*- coding: utf-8 -*-
"""
Created on Fri Feb 28 08:49:34 2020
"""
import arcpy , m_main_layer
class Toolbox(object):
def __init__(self):
"""Define the toolbox (the name of the toolbox is the name of the .pyt file)."""
self.label = "My Toolbox"
self.alias = ""
# List of tool classes associated with this toolbox
self.tools = [FeatureOff, FeatureOn]
class FeatureOff(object):
def __init__(self):
"""Define the tool (tool name is the name of the class)."""
self.label = "Hide selected features"
self.description = "Hides selected features by applying a layer definition query"
self.canRunInBackground = False
def getParameterInfo(self):
"""Define parameter definitions"""
return
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."""
return
def execute(self, parameters, messages):
reload(m_main_layer)
m_main_layer.main_off()
return
class FeatureOn(object):
def __init__(self):
"""Define the tool (tool name is the name of the class)."""
self.label = "Display hidden features"
self.description = "displays hidden features by removing layer definition query"
self.canRunInBackground = False
def getParameterInfo(self):
"""Define parameter definitions"""
return
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."""
return
def execute(self, parameters, messages):
reload(m_main_layer)
m_main_layer.main_on()
return
Here the main Python script:
# -*- coding: utf-8 -*-
"""
Created on Fri Mar 20 09:11:37 2020
"""
# -*- coding: utf-8 -*-
import arcpy
# mark start of query condition
# comments such as /* -- */ do not work with FGDB
# therefore we add a dummy condition as start marker
query_start_marker = "'A'='A'"
query_concat = " AND "
# max value might be different for each database system in use:
max_num_selected_features_per_layer = 999
def remove_filter_features(lyr):
if not lyr.isFeatureLayer:
return
desc = arcpy.Describe(lyr.name)
query = lyr.definitionQuery
start = query.find(query_start_marker)
if start >= 0:
query_front = query[:start]
len_query_conact = len(query_concat)
if len(query_front) > len_query_conact and query_front[-len_query_conact:] == query_concat:
query_front = query_front[:-len_query_conact]
lyr.definitionQuery = query_front
def apply_filter_selected_features(lyr):
if not lyr.isFeatureLayer:
return
desc = arcpy.Describe(lyr.name)
if desc.FIDSet != '':
fid_list = desc.FIDSet.split(";")
if len(fid_list) > max_num_selected_features_per_layer:
arcpy.AddMessage("Too many features selected ({0}), max: {1}.".format(len(fid_list),max_num_selected_features_per_layer))
return
query = ' {} NOT IN ({}) '.format(desc.OIDFieldName, ",".join(fid_list))
existing_query = lyr.definitionQuery
if existing_query:
query = existing_query + query_concat + query_start_marker+ ' AND ' + query
else:
query = query_start_marker + ' AND ' + query
lyr.definitionQuery = query
arcpy.SelectLayerByAttribute_management(lyr, "CLEAR_SELECTION")
def main_off():
arcpy.AddMessage("hide selected features....")
mxd = arcpy.mapping.MapDocument("CURRENT")
df = arcpy.mapping.ListDataFrames(mxd)[0]
for l in arcpy.mapping.ListLayers(df):
apply_filter_selected_features(l)
arcpy.AddMessage("hide selected features....finished")
def main_on():
arcpy.AddMessage("display hidden features....")
mxd = arcpy.mapping.MapDocument("CURRENT")
df = arcpy.mapping.ListDataFrames(mxd)[0]
for l in arcpy.mapping.ListLayers(df):
remove_filter_features(l)
arcpy.RefreshActiveView()
arcpy.AddMessage("display hidden features....finished")
Example:
|
select features... |
|
...hidden... |
|
...bringing them back to screen... |