I have created a Python addin for ArcMap. It has two comboboxes.
Combobox1: Search for facility by name. If there is one facility with that name the mxd zooms to the selected extent.
Combobox2: If there are multiple facilities with that name the results populate combobox2. Map zooms to selection made from this combobox.
the script is relatively fast until it enters # Conditional statements based on facility code.
It's running through all the condition branches before executing the true one.
It's kind of a noob question but how can I make this more efficient? A break?
Here is my code:
import arcpy
from arcpy import env
import pythonaddins
env.workspace = r"PATH.sde"
eadFacil = "FEATURECLASS"
class Facility(object):
"""Implementation for EADpart2_addin.FacililtySearch (ComboBox)"""
def __init__(self):
self.items = []
self.editable = True
self.enabled = True
self.dropdownWidth = '12345467890'
self.width = '12345467890'
def onSelChange(self, selection):
pass
def onEditChange(self, text):
global query
query = text
print(query)
def onFocus(self, focused):
pass
def onEnter(self):
# Set current mxd and dataframe.
mxd = arcpy.mapping.MapDocument("CURRENT")
df = arcpy.mapping.ListDataFrames(mxd, "")[0]
# Make TableView
# env.workspace = r"C:\Users\brad.jones\AppData\Roaming\ESRI\Desktop10.3\ArcCatalog\[email protected]"
# eadFacil = "SDE.sewerman.tblEADFacilities"
table = arcpy.MakeTableView_management(eadFacil, "results", "Name like '%" + query + "%'")
print(table)
result = arcpy.GetCount_management(table)
count = int(result.getOutput(0))
print(count)
# Conditional statement based on number of results returned.
if count == 1:
with arcpy.da.SearchCursor(table, ["BO", "Factype"], "Name" + " like '%" + query + "%'") as cursor:
for row in cursor:
building = row[0]
print building
code = row[1]
print code
# Conditional statements based on facility code.
if code == "4":
# Clear all previous selections.
arcpy.SelectLayerByAttribute_management("FOG (4)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Categorical Industrial (1)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Significant Industrial (2)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Non-Significant Industrial (3)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Meter", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Survey", "CLEAR_SELECTION")
# Create Layer object.
lyr = arcpy.mapping.ListLayers(mxd, "FOG (4)", df)[0]
print lyr
# Select building by BO number.
arcpy.SelectLayerByAttribute_management("FOG (4)",
"NEW_SELECTION",
"SDE_SEWERMAN_BO_BO_UNIQ = '" + str(building) + "'")
print("Selection made.")
# Set map extent based on selection.
df.extent = lyr.getSelectedExtent(False)
df.scale = df.scale * 5
arcpy.RefreshActiveView()
elif code == "1":
# Clear all previous selections
arcpy.SelectLayerByAttribute_management("FOG (4)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Categorical Industrial (1)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Significant Industrial (2)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Non-Significant Industrial (3)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Meter", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Survey", "CLEAR_SELECTION")
# Create Layer object
lyr = arcpy.mapping.ListLayers(mxd, "Categorical Industrial (1)", df)[0]
print lyr
# Select building by BO number.
arcpy.SelectLayerByAttribute_management("Categorical Industrial (1)",
"NEW_SELECTION",
"SDE_SEWERMAN_BO_BO_UNIQ = '" + str(building) + "'")
print("Selection made.")
# Set map extent based on selection.
df.extent = lyr.getSelectedExtent(False)
df.scale = df.scale * 5
arcpy.RefreshActiveView()
elif code == "2":
# Clear all previous selections
arcpy.SelectLayerByAttribute_management("FOG (4)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Categorical Industrial (1)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Significant Industrial (2)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Non-Significant Industrial (3)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Meter", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Survey", "CLEAR_SELECTION")
# Create Layer object
lyr = arcpy.mapping.ListLayers(mxd, "Significant Industrial (2)", df)[0]
print lyr
# Select building by BO number.
arcpy.SelectLayerByAttribute_management("Significant Industrial (2)",
"NEW_SELECTION",
"SDE_SEWERMAN_BO_BO_UNIQ = '" + str(building) + "'")
print("Selection made.")
# Set map extent based on selection.
df.extent = lyr.getSelectedExtent(False)
df.scale = df.scale * 5
arcpy.RefreshActiveView()
elif code == "3":
# Clear all previous selections
arcpy.SelectLayerByAttribute_management("FOG (4)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Categorical Industrial (1)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Significant Industrial (2)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Non-Significant Industrial (3)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Meter", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Survey", "CLEAR_SELECTION")
# Create Layer object
lyr = arcpy.mapping.ListLayers(mxd, "Non-Significant Industrial (3)", df)[0]
print lyr
# Select building by BO number.
arcpy.SelectLayerByAttribute_management("Non-Significant Industrial (3)",
"NEW_SELECTION",
"SDE_SEWERMAN_BO_BO_UNIQ = '" + str(building) + "'")
print("Selection made.")
# Set map extent based on selection.
df.extent = lyr.getSelectedExtent(False)
df.scale = df.scale * 5
arcpy.RefreshActiveView()
elif code == "M":
# Clear all previous selections
arcpy.SelectLayerByAttribute_management("FOG (4)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Categorical Industrial (1)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Significant Industrial (2)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Non-Significant Industrial (3)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Meter", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Survey", "CLEAR_SELECTION")
# Create Layer object
lyr = arcpy.mapping.ListLayers(mxd, "Meter", df)[0]
print lyr
# Select building by BO number.
arcpy.SelectLayerByAttribute_management("Meter",
"NEW_SELECTION",
"SDE_SEWERMAN_BO_BO_UNIQ = '" + str(building) + "'")
print("Selection made.")
# Set map extent based on selection.
df.extent = lyr.getSelectedExtent(False)
df.scale = df.scale * 5
arcpy.RefreshActiveView()
elif code == "S":
# Clear all previous selections
arcpy.SelectLayerByAttribute_management("FOG (4)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Categorical Industrial (1)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Significant Industrial (2)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Non-Significant Industrial (3)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Meter", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Survey", "CLEAR_SELECTION")
# Create Layer object
lyr = arcpy.mapping.ListLayers(mxd, "Survey", df)[0]
print lyr
# Select building by BO number.
arcpy.SelectLayerByAttribute_management("Survey",
"NEW_SELECTION",
"SDE_SEWERMAN_BO_BO_UNIQ = '" + str(building) + "'")
print("Selection made.")
# Set map extent based on selection.
df.extent = lyr.getSelectedExtent(False)
df.scale = df.scale * 5
arcpy.RefreshActiveView()
else:
print("Somethin' got !%$#& up.")
pythonaddins.MessageBox("Something weird has happened for you to have gotten this message. "
"Try restarting ArcMap and running the tool again."
"Contact Bradley Jones if the problem persist.", "Wrong 'Em Boyo",
0)
elif count == 0:
pythonaddins.MessageBox("No facilities found.", "EAD Facility Results", 0)
print("No results found")
else:
print "Number of facilities found: {0}".format(count)
pythonaddins.MessageBox("Multiple facilities found. See 'Results' list.",
"EAD Facility Results",
0)
del mxd, df
def refresh(self):
pass
class Results(object):
"""Implementation for EADpart2_addin.Results (ComboBox)"""
def __init__(self):
self.items = []
self.editable = True
self.enabled = True
self.dropdownWidth = '1234567890123456789012345678901234567890'
self.width = '1234546789012345467890'
def onSelChange(self, selection):
# Set current mxd and dataframe.
mxd = arcpy.mapping.MapDocument("CURRENT")
df = arcpy.mapping.ListDataFrames(mxd, "")[0]
# Make Query Table
env.workspace = r"C:\Users\brad.jones\AppData\Roaming\ESRI\Desktop10.3\ArcCatalog\[email protected]"
eadFacil = "SDE.sewerman.tblEADFacilities"
table = arcpy.MakeTableView_management(eadFacil, "results", "Address = '" + selection + "'")
print(table)
result = arcpy.GetCount_management(table)
count = int(result.getOutput(0))
print(count)
with arcpy.da.SearchCursor(table, ["BO", "Factype"], "Name" + " like '%" + query + "%'") as cursor:
for row in cursor:
building = row[0]
print building
code = row[1]
print code
# Conditional statements based on facility code.
if code == "4":
# Clear all previous selections.
arcpy.SelectLayerByAttribute_management("FOG (4)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Categorical Industrial (1)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Significant Industrial (2)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Non-Significant Industrial (3)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Meter", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Survey", "CLEAR_SELECTION")
# Create Layer object.
lyr = arcpy.mapping.ListLayers(mxd, "FOG (4)", df)[0]
print lyr
# Select building by BO number.
arcpy.SelectLayerByAttribute_management("FOG (4)",
"NEW_SELECTION",
"SDE_SEWERMAN_BO_BO_UNIQ = '" + str(building) + "'")
print("Selection made.")
# Set map extent based on selection.
df.extent = lyr.getSelectedExtent(False)
df.scale = df.scale * 5
arcpy.RefreshActiveView()
elif code == "1":
# Clear all previous selections
arcpy.SelectLayerByAttribute_management("FOG (4)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Categorical Industrial (1)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Significant Industrial (2)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Non-Significant Industrial (3)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Meter", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Survey", "CLEAR_SELECTION")
# Create Layer object
lyr = arcpy.mapping.ListLayers(mxd, "Categorical Industrial (1)", df)[0]
print lyr
# Select building by BO number.
arcpy.SelectLayerByAttribute_management("Categorical Industrial (1)",
"NEW_SELECTION",
"SDE_SEWERMAN_BO_BO_UNIQ = '" + str(building) + "'")
print("Selection made.")
# Set map extent based on selection.
df.extent = lyr.getSelectedExtent(False)
df.scale = df.scale * 5
arcpy.RefreshActiveView()
elif code == "2":
# Clear all previous selections
arcpy.SelectLayerByAttribute_management("FOG (4)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Categorical Industrial (1)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Significant Industrial (2)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Non-Significant Industrial (3)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Meter", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Survey", "CLEAR_SELECTION")
# Create Layer object
lyr = arcpy.mapping.ListLayers(mxd, "Significant Industrial (2)", df)[0]
print lyr
# Select building by BO number.
arcpy.SelectLayerByAttribute_management("Significant Industrial (2)",
"NEW_SELECTION",
"SDE_SEWERMAN_BO_BO_UNIQ = '" + str(building) + "'")
print("Selection made.")
# Set map extent based on selection.
df.extent = lyr.getSelectedExtent(False)
df.scale = df.scale * 5
arcpy.RefreshActiveView()
elif code == "3":
# Clear all previous selections
arcpy.SelectLayerByAttribute_management("FOG (4)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Categorical Industrial (1)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Significant Industrial (2)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Non-Significant Industrial (3)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Meter", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Survey", "CLEAR_SELECTION")
# Create Layer object
lyr = arcpy.mapping.ListLayers(mxd, "Non-Significant Industrial (3)", df)[0]
print lyr
# Select building by BO number.
arcpy.SelectLayerByAttribute_management("Non-Significant Industrial (3)",
"NEW_SELECTION",
"SDE_SEWERMAN_BO_BO_UNIQ = '" + str(building) + "'")
print("Selection made.")
# Set map extent based on selection.
df.extent = lyr.getSelectedExtent(False)
df.scale = df.scale * 5
arcpy.RefreshActiveView()
elif code == "M":
# Clear all previous selections
arcpy.SelectLayerByAttribute_management("FOG (4)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Categorical Industrial (1)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Significant Industrial (2)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Non-Significant Industrial (3)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Meter", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Survey", "CLEAR_SELECTION")
# Create Layer object
lyr = arcpy.mapping.ListLayers(mxd, "Meter", df)[0]
print lyr
# Select building by BO number.
arcpy.SelectLayerByAttribute_management("Meter",
"NEW_SELECTION",
"SDE_SEWERMAN_BO_BO_UNIQ = '" + str(building) + "'")
print("Selection made.")
# Set map extent based on selection.
df.extent = lyr.getSelectedExtent(False)
df.scale = df.scale * 5
arcpy.RefreshActiveView()
elif code == "S":
# Clear all previous selections
arcpy.SelectLayerByAttribute_management("FOG (4)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Categorical Industrial (1)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Significant Industrial (2)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Non-Significant Industrial (3)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Meter", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Survey", "CLEAR_SELECTION")
# Create Layer object
lyr = arcpy.mapping.ListLayers(mxd, "Survey", df)[0]
print lyr
# Select building by BO number.
arcpy.SelectLayerByAttribute_management("Survey",
"NEW_SELECTION",
"SDE_SEWERMAN_BO_BO_UNIQ = '" + str(building) + "'")
print("Selection made.")
# Set map extent based on selection.
df.extent = lyr.getSelectedExtent(False)
df.scale = df.scale * 5
arcpy.RefreshActiveView()
else:
print("Somethin' got !%$#& up.")
pythonaddins.MessageBox("Something weird has happened for you to have gotten this message. "
"Try restarting ArcMap and running the tool again."
"Contact Bradley Jones if the problem persist.", "Wrong 'Em Boyo",
0)
del mxd, df
def onEditChange(self, text):
pass
def onFocus(self, focused):
# Empty list to populate from from TableView
firstList = []
# Empty the Combobox items list which will receive rows without duplicates
self.items = []
# Establish a reference to the current MXD
mxd = arcpy.mapping.MapDocument("Current")
print mxd
# Establish a reference to the first DataFrame object in the current MXD
df = arcpy.mapping.ListDataFrames(mxd)[0]
print df
# Create table object for results TableView
tableList = arcpy.mapping.ListTableViews(mxd, "results", df)
print tableList
# Populate firstList which will have duplicates.
for table in tableList:
with arcpy.da.SearchCursor(table, ["Address"]) as cursor:
for row in cursor:
firstList.append(row)
print row
# Populate self.items without duplicates.
for i in firstList:
if i not in self.items:
self.items.append(i)
print i
print(self.items)
del mxd, df
def onEnter(self):
pass
def refresh(self):
pass
-
3So the layers you are selecting from, how many rows are there it is always selecting from, 100 or 10,000,000? Have you added an attribute index to the field you are selecting by?Hornbydd– Hornbydd2016年04月26日 21:47:12 +00:00Commented Apr 26, 2016 at 21:47
-
Largest layer has 946 rows (code 4). First in if/else branch. Others are 225, 89, 14, 19, and 11. Overall it takes 20-25 sec to run. The smaller layers are around 20 sec.Brad Jones– Brad Jones2016年04月27日 11:29:34 +00:00Commented Apr 27, 2016 at 11:29
-
The "SDE_SEWERMAN_BO_BO_UNIQ" field isn't indexed. It's a unique value so that will probably help.Brad Jones– Brad Jones2016年04月27日 12:02:54 +00:00Commented Apr 27, 2016 at 12:02
-
Indexing the field didn't help much.Brad Jones– Brad Jones2016年04月27日 12:32:53 +00:00Commented Apr 27, 2016 at 12:32
1 Answer 1
You have some repeating processes that could probably be rearranged. It may help with speed.
Clearing all the layers' selections could be done at the beginning of the loop instead of within each if/else statement Edit (this may slow down the process since the clear selection happens every iteration):
if count == 1:
with arcpy.da.SearchCursor(table, ["BO", "Factype"], "Name" + " like '%" + query + "%'") as cursor:
for row in cursor:
building = row[0]
print building
code = row[1]
print code
arcpy.SelectLayerByAttribute_management("FOG (4)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Categorical Industrial (1)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Significant Industrial (2)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Non-Significant Industrial (3)", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Meter", "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management("Survey", "CLEAR_SELECTION")
Or do it within the if statements but only on the layer you are interested in. Or clear it right after you set your active view extent.
if code == "4":
# Create Layer object.
lyr = arcpy.mapping.ListLayers(mxd, "FOG (4)", df)[0]
print lyr
# Select building by BO number.
arcpy.SelectLayerByAttribute_management("FOG (4)","NEW_SELECTION","SDE_SEWERMAN_BO_BO_UNIQ = '" + str(building) + "'")
print("Selection made.")
# Set map extent based on selection.
df.extent = lyr.getSelectedExtent(False)
df.scale = df.scale * 5
arcpy.RefreshActiveView()
arcpy.SelectLayerByAttribute_management("FOG (4)", "CLEAR_SELECTION")
Note: It may be entirely unnecessary to clear anyway, since a New Selection will clear the current section.
You also are using a tableview that has the query, then in your search cursor you repeat that query. This shouldn't be necessary. The query on the table view should carry over to the search cursor.
table = arcpy.MakeTableView_management(eadFacil, "results", "Name like '%" + query + "%'")
print(table)
result = arcpy.GetCount_management(table)
count = int(result.getOutput(0))
print(count)
# Conditional statement based on number of results returned.
if count == 1:
with arcpy.da.SearchCursor(table, ["BO", "Factype"]) as cursor:
for row in cursor:
-
1Clearing the selection was the problem! I don't need it at all. Time went from 20-25 sec down to 4-6 sec. Interesting note: I moved the clear selection functions to your first suggestion and it ran a few seconds slower. Bit I don't need them.Brad Jones– Brad Jones2016年04月27日 18:11:22 +00:00Commented Apr 27, 2016 at 18:11
-
It probably slows down because the if statements didn't require it to run every loop. I'll make a note above so that is clear to anyone who reads this post.dslamb– dslamb2016年04月27日 18:21:15 +00:00Commented Apr 27, 2016 at 18:21