Select by Attributes (Date Range) from Hosted Survey123 Layer

363
4
12-15-2023 09:22 AM
GIS_Consultant_ASE
New Contributor

Hello All!

I am trying to build a script and that takes several layers, and selects by attribute only records in those layers within a given date range.   I am selecting from several hosted feature layers (point geometry) that are all within a single survey 123 hosted feature layer.  So there are parent records, and child+grandchild, and the date field they all share in common is called 'CreationDate' which is formatted as such: 12/6/2023 11:29:34 PM.  I am trying to run this as a script tool within ArcPro and a given .aprx.  Parameters are StartDate (Date, Input), EndDate (Date, Input), and SelectedLayers (Feature Layer, Input, Multiple Values Allowed)

When I run the script on a test copy of the data (same schema as real data I will eventually use), the script has print statements that indicate some records were selected and they are the ones I would expect.  However, that selection is not applied in the map.  When I open the table, it shows 0 records selected.  I do not understand why this is.  This is important because the next step of the script will be to use only those selected records within the give range to do a select by location process.  Any clue as to why the selection is not applied in the map but does show up in print statements as having happened (see screenshots)?   I want the next step to be: take only the selected records in the six S123 layers, and select by location all records within 50ft of those that intersect another feature class.  The Script and Screenshots are provided below.

 

 

 

import arcpy
from datetime import datetime

# Get the current ArcGIS Pro project
aprx_path = arcpy.mp.ArcGISProject("CURRENT").filePath

# Get input parameters from the user
start_date_str = arcpy.GetParameterAsText(0) # Start date as string (format: MM/DD/YYYY hh:mm:ss AM/PM)
end_date_str = arcpy.GetParameterAsText(1) # End date as string (format: MM/DD/YYYY hh:mm:ss AM/PM)
selected_layers = arcpy.GetParameterAsText(2).split(";") # Selected layers as a list

# Fixed date format for parsing
date_format = "%m/%d/%Y %I:%M:%S %p"

# Convert input date strings to datetime objects
start_date = datetime.strptime(start_date_str, date_format)
end_date = datetime.strptime(end_date_str, date_format)

# Open the ArcGIS project
aprx = arcpy.mp.ArcGISProject(aprx_path)

# Process selected layers
for layer_name in selected_layers:
# Access the map
maps = aprx.listMaps() # Get all maps in the project

# Check if the layer is within a group
if "\\" in layer_name:
group_name, layer_name = layer_name.split("\\")

# Strip leading and trailing spaces from the group name
group_name = group_name.strip()

# Try to find the group in any of the maps
group = None
for map_obj in maps:
try:
group = map_obj.listLayers(group_name)[0]
break # If group is found in any map, exit the loop
except IndexError:
pass # Ignore the error and continue searching in the next map

if group is None:
arcpy.AddError(f"Group '{group_name}' not found in any map.")
continue # Skip to the next layer

# Get the layers within the group
layers = [lyr for lyr in group.listLayers() if lyr.name == layer_name]
else:
# If not within a group, search for the layer in any of the maps
layers = [lyr for map_obj in maps for lyr in map_obj.listLayers(layer_name)]

if not layers:
arcpy.AddError(f"Layer '{layer_name}' not found in any map.")
continue

layer = layers[0]

# Create a query to select features within the specified date range
date_query = f"CreationDate >= date '{start_date.strftime('%m/%d/%Y %I:%M:%S %p')}' AND " \
f"CreationDate <= date '{end_date.strftime('%m/%d/%Y %I:%M:%S %p')}'"

# Debugging output: Print layer name and date query
arcpy.AddMessage(f"Processing Layer: {layer.name}")
arcpy.AddMessage(f"Date Query: {date_query}")

# Select features based on the date query
arcpy.management.SelectLayerByAttribute(layer, "NEW_SELECTION", date_query)

# Debugging output: Print the count of selected features
result = arcpy.GetCount_management(layer)
count = int(result.getOutput(0))
arcpy.AddMessage(f"Selected {count} features.")

 

 

ScriptToolResult.png

0 Kudos
4 Replies
Kara_Shindle
Occasional Contributor III

It would help if you could insert your code going forward using the "Insert code sample" button.

 

You open the Aprx before you make the selection.  Is the layer you are creating with your "select By attributes" actually getting added to the APRX?  The way I'm reading your code, you assign the first layer to your layer variable, and then feed that into your selectbyattribute tool.  

 

The reference says:

If the input is a feature class or dataset path, this tool will automatically create and return a new layer with the result of the tool applied.

Are you sure that new layer is getting added to your APRX?

 

Edit: If you were running this in the Python window in Pro, I think it would show your selection.  Since you're running it in a standalone Python script, I think you have to add your selection results to your APRX, maybe by creating a new layer as documented here

0 Kudos
GIS_Consultant_ASE
New Contributor

Thank you for the reply!  And I will add code in the appropriate place going forward😅  

So I think creating the new layer based on selection will make sense, particularly if I then need to use that selection as a basis for the next step.  However, I am not sure how that will work with a hosted feature layer based on Survey123.  I think I have correct permissions to do that, but it would be a lot of data to export I think.  Also, if I run it in the python window can the user still select a custom date range?  I wonder if going that route makes more sense.  As you can probably tell, I am new to this

0 Kudos
Kara_Shindle
Occasional Contributor III

the arcpy.GetParameterAsText is supposed to be used if you are making a tool out of this script.  Then it would map to a field in a tool dialog box that your user could input.  If you are using the Python window, I *think* your users would still have to manually update the date.  If you're going to deploy this for others, I'd suggest going the tool route.

0 Kudos
Kara_Shindle
Occasional Contributor III

Another thought:

If you are using the list of layers to perform a selection on, doesn't your layers = layers[0] only select the first selection in your list?  My first thought would be that you need some sort of for loop to go through each layer in your list and apply your selection.  The sample below isn't perfect, but this is what I was thinking.  

 

#for each layer in your selection
for layer in layers:
  #create a selection & write it to a temp layer
  selectedLayer = arcpy.management.SelectLayerByAttribute(in_layer_or_view, 
{selection_type}, {where_clause}, {invert_where_clause})
 
#Write selected features to a new feature class
 arcpy.management.CopyFeatures(selectedLayer, 'layer1')

 

0 Kudos