This code prints each layer's data source followed by a list of attributes that are used in the layer's definition query, labels, or symbology. Note that a single data source may be behind multiple layers. Also, not that I couldn't figure out a way to identify the fields used in "unique values, many fields" or "dot density" symbology.
import arcpy, os
mxd = arcpy.mapping.MapDocument(r'C:\temp\Untitled.mxd')
for layer in arcpy.mapping.ListLayers(mxd):
# If you can't identify the layer's source data (e.g., web services, group
# layers), then skip it
if not layer.supports('dataSource'):
ds = layer.dataSource
# Fields in the layer
fields = [i.name for i in arcpy.ListFields(ds)]
fields.sort(key=lambda s: len(s), reverse=True)
# A list of fields used in the map
fieldsUsed = list()
# Get the fields used in its symbology; note that this will only work
# for layers that have basic "Unique Values" symbology. Dot Density symbology
# and "unique values, many fields" symbology won't return the fields used.
if hasattr(layer, 'symbology'):
sym = layer.symbology
if hasattr(sym, 'valueField'):
field = sym.valueField
if hasattr(sym, 'normalization'):
field = sym.normalization
# Get the fields used in its definition query
if hasattr(layer, 'definitionQuery'):
dq = layer.definitionQuery
for field in fields:
if field in dq:
dq = dq.replace(field, '')
if hasattr(layer, 'labelClasses'):
# Get the fields used in the labels
lcs = layer.labelClasses
for lc in lcs:
lcSQL = lc.SQLQuery
lcExp = lc.expression
for field in fields:
if field in lcSQL:
lcSQL = lcSQL.replace(field, '')
if field in lcExp:
lcExp = lcExp.replace(field, '')
# Remove repeated field names
fieldsUsed = list(set(fieldsUsed))
# Print out the fields used
for f in fieldsUsed:
Updated the code to be more versatile and not crash in the face of rasters, group layers, and feature services.
Here are details on the layer properties. For the symbology properties, see the paragraph that begins "Depending on the symbology type". As it mentions there, the "OTHER" symbologyType "represents an unsupported layer symbology class". Unfortunately, this includes the many fields symbology. However, tweaking the work-around presented here, you might be able to pull it off.
Also, note that this script may over-select fields. For example, if you have field named 'F1' and you have a definition query or a label class query like "MyTextField = 'Blah blah and F1 blah'". Then, F1 would be returned, even though the literal string 'F1' is being used in the query and not the field name. It turns out that these types of scenarios are extremely difficult to account for, and based on a google search, no one has been able to accomplish the feat. That said, you could address many query scenarios with some relatively simple regex.
EDIT: Updated the code to prevent conflation of fields named, e.g., 'F1', 'F11', 'F111'. In the previous version, the appearance of F111 in a definition query or label query would have yielded all three field names in the output.