In ArcMap Pro, how to get data from a selected layer

4368
19
Jump to solution
04-30-2019 11:38 AM
jasongraham
New Contributor III

I am using python in ArcPro and relearning a few things.

I have a feature selected in the dataframe.  I want to determine the name of that layer that has a selection and return the value of the selected object in the field called "GNIS_Name" .  

aprx = arcpy.mp.ArcGISProject("CURRENT")

#get selected layer 
m = aprx.listMaps(aprx)
refLyr = m.listLayers(aprx) 
sel_lyrs = refLyr.getSelectionSet(aprx)

# get name of selected stream    
Stream_Name = arcpy.da.SearchCursor(sel_lyrs, "GNIS_Name", "Any value", "")‍‍‍‍‍‍‍

currently I get the error on line 5: 'list' object has no attribute 'listLayers'

0 Kudos
1 Solution

Accepted Solutions
JoshuaBixby
MVP Esteemed Contributor
aprx = arcpy.mp.ArcGISProject("CURRENT")
m = aprx.activeMap
lyrs = m.listLayers()
for lyr in lyrs:
    if lyr.getSelectionSet():
        print("{}: {}".format(lyr.name, lyr.getSelectionSet()))

View solution in original post

19 Replies
JoshuaBixby
MVP Esteemed Contributor
aprx = arcpy.mp.ArcGISProject("CURRENT")
m = aprx.activeMap
lyrs = m.listLayers()
for lyr in lyrs:
    if lyr.getSelectionSet():
        print("{}: {}".format(lyr.name, lyr.getSelectionSet()))
jasongraham
New Contributor III

Thanks, this gets me a few steps closer.

0 Kudos
jasongraham
New Contributor III

However, in my next step, I want to take the name of that selected layer and get a field value

Stream_Name = arcpy.da.SearchCursor(lyrs, "GNIS_Name", "Any value", "")‍‍‍

I get the error 

RuntimeError: 'in_table' is not a table or a featureclass

Am I taking the wrong approach?  it seems to pass as a layer and not a feature class.

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

There appears to be quite a bit going on, or going wrong, with your search cursor syntax.  Starting with the first parameter, you are passing lyrs, which is a list.  ArcPy cursors can't operate on Python lists. The second parameter seems OK, assuming "GNIS_NAME" is the name of the field in question.  I am unclear what you mean by "Any Value" for the third parameter.  The third positional parameter is an SQL WHERE clause, and I am not sure how to interpret what you are passing.

0 Kudos
jasongraham
New Contributor III

well I am learning a lot of ways not to do it.  This statement will print the all the names, not just the selected row

aprx = arcpy.mp.ArcGISProject("CURRENT")
m = aprx.activeMap
lyrs = m.listLayers()
for lyr in lyrs:
    if lyr.getSelectionSet():
       sel_lyr = lyr.dataSource
       sel_oid = lyr.getSelectionSet()
       with arcpy.da.SearchCursor(sel_lyr,"GNIS_Name") as cursor:
           for row in cursor:
               print(row)

All I want is to know the path of the layer that has a selected feature, and know what the name is in the "GNIS_Name" Field  of that selected feature

the lyr.getSelectionSet will give me the data source and the OID of the selected row.

I have tried to use an SQL in the search cursor like this

with arcpy.da.SearchCursor(sel_lyr,"GNIS_Name",'OID@' = sel_oid) as cursor:

and many variations like that, but always get a syntax error.  is my entire approach wrong?

I orignially did the project in MB but elected to move to Python. I essentially need a Get Field Value function.

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

ArcPy cursors honor selection sets on layers and table views.  Instead of retrieving the the data source of the layer and passing that to the cursor, just pass the layer itself.

0 Kudos
RandyBurton
MVP Alum
# instead of OID@
with arcpy.da.SearchCursor(sel_lyr,"GNIS_Name",'OID@' = sel_oid) as cursor:

# try OBJECTID or the field's actual name instead of a token
# also note the quotes around the sql part
with arcpy.da.SearchCursor(sel_lyr,"GNIS_Name","OBJECTID = sel_oid") as cursor:‍‍‍‍‍‍
0 Kudos
jasongraham
New Contributor III

Thanks for the help!  This is what works:

import arcpy
aprx = arcpy.mp.ArcGISProject("CURRENT")
m = aprx.activeMap
lyrs = m.listLayers()
for lyr in lyrs:
    if lyr.getSelectionSet():
       sel_lyr = lyr.dataSource
       field = "GNIS_Name"
       rows = arcpy.da.SearchCursor(lyr,field)
       for row in rows:
            print(row[0])

now off for the rest of the code....

0 Kudos
jasongraham
New Contributor III

I should probably start a new question, by thought I would check here first.  This code will run all the way through, all the fields gat added but the one at line 139 with the code block does nothing and I dont get any errors.  I have tried changing the " to ' changing all the quotes and do not see any changes.  

am I doing the codeblock wrong?

# -*- coding: utf-8 -*-

'''---------------------------------------------------------------------------
# Exposed.py
# Created on: 2019-04-10 Jason Graham
#
# Usage: For classifying hazard level from winds on cops of trees near 
# Anadromous streams Primary and secondary previaling winds.
# 
# Paramters <Workspace> 
#           <Prevailing_Wind_Direction> 
#           <Secondary_Prevailing_Wind_Direction>  
#           Selected Stream with a GNIS_Name field
#
# Description:
# When a stream is selected this tool will create a buffer for each side of a
# stream and use the direction of the prevailing and secondary winds to 
# calculate a Wind Exposure class for each section of major angles along 
# the stream.
# ---------------------------------------------------------------------------
'''
# Import arcpy module (14)
import arcpy as arcpy, datetime
import os

arcpy.env.overwriteOutput = True
arcpy.env.workspace = 'in_memory'

startTime = datetime.datetime.now()
arcpy.AddMessage ('Start processing at :')
arcpy.AddMessage (startTime.strftime('%Y-%m-%d %H:%M'))
 
# Get Parameters from user
workspace = arcpy.GetParameterAsText(0)
windP = arcpy.GetParameterAsText(1)
windS = arcpy.GetParameterAsText(2)

# Current workspace
aprx = arcpy.mp.ArcGISProject('CURRENT')
m = aprx.activeMap

# Get Selected stream info
lyrs = m.listLayers()

for lyr in lyrs:
    if lyr.getSelectionSet():
       sel_lyr = lyr.dataSource
       field = 'GNIS_Name'
       rows = arcpy.da.SearchCursor(lyr,field)
       for row in rows:
            # get name of selected stream
            Stream_Pre = row[0]
            # replaces spaces with underscore
            Stream_Name = Stream_Pre.replace(' ','_')

# Local variables:
stream = os.path.join(str(workspace),Stream_Name)

# Main Body of Script

arcpy.cartography.SimplifyLine(sel_lyr, stream, 'POINT_REMOVE', '45 Meters', 
                               'RESOLVE_ERRORS', 'NO_KEEP', 'CHECK', '')

arcpy.management.SplitLine(stream,stream + '_Split')

# Buffer the stream(Right)

arcpy.Buffer_analysis(stream + '_Split' , stream + '_Buff', '63 Feet', 'RIGHT'
                      , 'FLAT', 'NONE', '', 'PLANAR')

# Add Field named Angle

arcpy.AddField_management(stream + '_Buff', 'Angle', 'LONG', '', '', '', '', 
                          'NULLABLE', 'NON_REQUIRED', '')

# Process: Calculate Polygon Main Angle (R)

arcpy.CalculatePolygonMainAngle_cartography(stream + '_Buff', 'Angle', 
                                            'GEOGRAPHIC')

# Process: Add Field (Wind)

arcpy.AddField_management(stream + '_Buff', 'wind', 'LONG', '', '', '20', '', 
                          'NULLABLE', 'REQUIRED', '')

arcpy.CalculateField_management(stream + '_Buff', 'wind', windP)

# Process: Calculate Field (Adjust Angle R)
expression1 = 'getClass((!Angle!)+ !wind!)'

codeblock1 = '''
def getClass(n):
    if n < 0:
        return n * -1
    else:   
        return n'''

arcpy.CalculateField_management(stream + '_Buff', 'wind', expression1, 
                                'PYTHON3', codeblock1)

# Process: Add Field (Wind2_R)
arcpy.AddField_management(stream + '_Buff', 'wind2', 'LONG', '', '', '20', '', 
                          'NULLABLE', 'NON_REQUIRED', '')
 
arcpy.CalculateField_management(stream + '_Buff', 'wind2', windS)

# Process: Calculate Field (Adjust Secondary Angle R)
expression2 = 'getClass((!Angle!)+ !wind2!)'

arcpy.CalculateField_management(stream + '_Buff', 'wind2', expression2, 
                                'PYTHON3', codeblock1)

# Process: Add Field (Index_R)
arcpy.AddField_management(stream + '_Buff', 'Index', 'LONG', '', '', '20', '', 
                          'NULLABLE', 'REQUIRED', '')

# Process: Calculate Field (Index R)
expressionReclass = "Reclass(!wind!)"
codeblock_wind ='''def Reclass(wind):
	if (wind >= 0 and wind <= 20):
		return 5
	elif (wind > 20 and wind <= 70):
		return 4
	elif (wind > 70 and wind <= 110):
		return 3
	elif (wind > 110 and wind <=160):
		return 2
	elif(wind > 160 and wind <=200):
		return 1
	elif(wind > 200 and wind <=250):
		return 2
	elif(wind > 250 and wind <=290):
		return 3
	elif(wind > 290 and wind <=340):
		return 4
	elif(wind > 340):
		return 5'''

arcpy.CalculateField_management(stream + '_Buff', 'Index', expressionReclass, 
                                'PYTHON_9.3', codeblock_wind)

# Process: Add Field (Index2_R)
arcpy.AddField_management(stream + '_Buff', 'Index2', 'LONG', '', '', '20', '',
                          'NULLABLE', 'NON_REQUIRED', '')

# Process: Calculate Field (Index2 R)
expressionReclass2 = 'Reclass(!wind2!)'
codeblock_wind2 = '''def Reclass(wind2):
	if (wind2 >= 0 and wind2 <= 20):
		return 5
	elif (wind2 > 20 and wind2 <= 70):
         	return 4
	elif (wind2 > 70 and wind2 <= 110):
	    	return 3
	elif (wind2 > 110 and wind2 <=160):
	    	return 2
	elif(wind2 > 160 and wind2 <=200):
	    	return 1
	elif(wind2 > 200 and wind2 <=250):
	    	return 2
	elif(wind2 > 250 and wind2 <=290):
	    	return 3
	elif(wind2 > 290 and wind2 <=340):
	    	return 4
	elif(wind2 > 340):
	    	return 5'''       
arcpy.CalculateField_management(stream + '_Buff', 'Index', expressionReclass2, 
                                'PYTHON_9.3', codeblock_wind2)
        
# Process: Add Field (Sum_R)
arcpy.AddField_management(stream + '_Buff', 'SumOfRanks', 'SHORT', '', '', 
                          '20', '', 'NULLABLE', 'NON_REQUIRED', '')

# Process: Calculate Field (Add Index R)
arcpy.CalculateField_management(stream + '_Buff', 'Index', '!Index!+ !Index2!',
                                'PYTHON_9.3', '')

# Process: Add Field (Class_R)
arcpy.AddField_management(stream + '_Buff', 'Class', 'SHORT', '', '', '20', '',
                          'NULLABLE', 'NON_REQUIRED', '')

# Process: Calculate Field (Class R)
codeblock3 = '''
def Reclass(SumOfRanks):
	if (SumOfRanks >= 0 and SumOfRanks <= 1):
		return 1
	elif (SumOfRanks > 1 and SumOfRanks <= 4):
		return 2
	elif (SumOfRanks > 4 and SumOfRanks <= 6):
		return 3
	elif (SumOfRanks > 6 and SumOfRanks <= 8):
		return 4
	elif (SumOfRanks > 8 and SumOfRanks <= 10):
		return 5'''
    
arcpy.CalculateField_management(stream + '_Buff', 'Index', 
                                'Reclass(!SumOfRanks!)', 'PYTHON_9.3'
                                ,codeblock3)

# add new layer and delete extra layers
m.addDataFromPath (stream + '_Buff')

#arcpy.DeleteFeatures_management (stream)
#arcpy.DeleteFeatures_management (stream + '_Split')

endTime = datetime.datetime.now()
arcpy.AddMessage ('Finished processing at :')
arcpy.AddMessage (endTime.strftime('%Y-%m-%d %H:%M'))
arcpy.AddMessage ('Process duration:')
arcpy.AddMessage (endTime - startTime)
0 Kudos