This Python script will get you halfway there (note: tested only on 10.3.1 but should still work on 10.6). The code is verbose to illustrate what is going on, feel free to optimise. It creates a polygon object based on the extent of the first data frame in the MXD. It then uses that polygon in a Select Layer By Location operation. It then uses a search cursor on the selected features to create a list of attributes. Finally it updates a text element on the layout with the list of attributes.
It does not automatically update the text element when the data frame extent changes. As mentioned in the comments, you'll probably need to use ArcObjects to get that level of functionality.
The script runs from within ArcMap and you can use it as is. I've just run it from the Python console with
execfile(r"E:\Temp\Select_Features_Within_Data_Frame.py")
It would be more usable if you incorporate the logic into a Python add-in and build a method for specifying multiple layers and fields as inputs.
You will need to modify the aSelectLayer
and aSelectField
variables to suit your data. You will also need to add a text element on your layout with the Element Name of "Features_in_Data_Frame". I suggest adding it as Rectangle Text so that it can automatically handle text that may overflow one line.
import arcpy
# ---------------------------------------------------------------------------
def GetAttributeList(aLyr, aField):
aList = []
with arcpy.da.SearchCursor(aLyr, aField) as aRows:
for aRow in aRows:
aList.append(aRow[0])
return aList
# ---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
def FeatCount(aLyr):
return int(arcpy.GetCount_management(aLyr).getOutput(0))
# ---------------------------------------------------------------------------
aSelectLayer = "test_pnt"
aSelectField = "UFI"
aMXD = arcpy.mapping.MapDocument("CURRENT")
df = arcpy.mapping.ListDataFrames(aMXD)[0]
aExtents = df.extent
Xmin = aExtents.XMin
Ymin = aExtents.YMin
Xmax = aExtents.XMax
Ymax = aExtents.YMax
aPnt1 = arcpy.Point(Xmin, Ymin)
aPnt2 = arcpy.Point(Xmin, Ymax)
aPnt3 = arcpy.Point(Xmax, Ymax)
aPnt4 = arcpy.Point(Xmax, Ymin)
aArray = arcpy.Array()
aArray.append(aPnt1)
aArray.append(aPnt2)
aArray.append(aPnt3)
aArray.append(aPnt4)
aPoly = arcpy.Polygon(aArray)
arcpy.SelectLayerByLocation_management(aSelectLayer,"WITHIN",aPoly,"#","NEW_SELECTION")
if FeatCount(aSelectLayer) > 0:
aValues = GetAttributeList(aSelectLayer, aSelectField)
# Update the text element in the layout
elm = arcpy.mapping.ListLayoutElements(aMXD, "TEXT_ELEMENT", "Features_in_Data_Frame")[0]
elm.text = "; ".join(aValues)
arcpy.SelectLayerByAttribute_management(aSelectLayer, "CLEAR_SELECTION")
arcpy.RefreshActiveView()
EDIT
I just noticed that if you change the data frame extent to somewhere where there are no features and run the script, the text element will not update. Just add the following to the bottom of the if clause:
else:
elm = arcpy.mapping.ListLayoutElements(aMXD, "TEXT_ELEMENT", "Features_in_Data_Frame")[0]
elm.text = "No features in extent"