2

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\GISVIEWER@SQL1.sde"
        # 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\GISVIEWER@SQL1.sde"
        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
  • 3
    So 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 Apr 26 '16 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 Apr 27 '16 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 Apr 27 '16 at 12:02
  • Indexing the field didn't help much. – Brad Jones Apr 27 '16 at 12:32
3

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:
  • 1
    Clearing 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 Apr 27 '16 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 Apr 27 '16 at 18:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.