4

Recently created my first Python Add-In for ArcMap. It has been deployed for about a month now and the users like it. There is one thing I want to fix. The Add-in has two combo boxes:

combo box

In #1 the user enters a facility name in the "Facility" combo box (red). If there is only 1 facility with that name the mxd will zoom to that feature. However, if there's more than one facility with that name the "Results" combo box (blue) will be populated with a list of addresses for facilities with that name.

In #2 the user has selected from the results list and the mxd zooms to that feature.

In #3 they search for another facility. At this point the results will remain populated with results from the last search where you had more than one facility with the same name. This is the case until the user does another search and populates the results with a new list.

I would like for the tool to clear the "Results" combo box whenever the user starts to type in the "Facility" combo box. I'm not sure how to clear the list on the results class from the onEditChange function in the Facility class.

Here is the code:

import arcpy
from arcpy import env
import pythonaddins
import time


class Facility(object):
    """Implementation for EAD_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)

        # Check to see if EAD layers are in mxd.
        mxd = arcpy.mapping.MapDocument("CURRENT")
        df = arcpy.mapping.ListDataFrames(mxd, "")[0]
        layer_list = arcpy.mapping.ListLayers(mxd, "EAD Facilities", df)
        print(layer_list)
        if len(layer_list) == 0:
            print("EAD Facilities not present")
            pythonaddins.MessageBox("'EAD Facilities' layer group must be added to map.", "Layers Present", 0)

            # Open the OpenDialog (add data) and create the objects list for use in Addlayer.
            ead_layer_file = pythonaddins.OpenDialog("Add 'EAD Facilities'",
                                                     "False",
                                                     r"O:\PATH\PATH\More Layers",
                                                     "Open")
            print(ead_layer_file)
            for layer in ead_layer_file:
                # Create object for layer in list.
                ead_lyr = arcpy.mapping.Layer(layer)
                print(ead_lyr)
                # Add object to mxd.
                arcpy.mapping.AddLayer(df, ead_lyr)
                print("Layer added")

        else:
            print("EAD Facilities is present")

    def onFocus(self, focused):
        pass

    def onEnter(self):
        startTime = time.time()

        # Set current mxd and dataframe.
        mxd = arcpy.mapping.MapDocument("CURRENT")
        df = arcpy.mapping.ListDataFrames(mxd, "")[0]

        # Make TableView
        env.workspace = r"O:\\PATH\PATH\sde"
        env.overwriteOutput = True
        eadFacil = "SDE.SDE.tblEADFacilities"
        table_view = arcpy.MakeTableView_management(eadFacil, "resultsView",  "Name like '%" + query + "%'")
        print(table_view)

        # Create summary statistics table to exclude duplicate facilities- get first occurrence of "ID"
        summary = arcpy.Statistics_analysis(table_view,
                                            r"in_memory\summaryTable",
                                            [["ID", "FIRST"],
                                             ["ADDRESS", "COUNT"],
                                             ["BO", "COUNT"],
                                             ["Factype", "COUNT"]],
                                            ["ADDRESS", "BO", "Factype"])
        print(summary)

        result = arcpy.GetCount_management(summary)
        count = int(result.getOutput(0))
        print("Facility count: " + str(count))

        # Conditional statement based on number of results returned.
        if count == 1:
            with arcpy.da.SearchCursor(summary, ["BO", "Factype"]) as cursor:
                for row in cursor:
                    building = row[0]
                    print ("building number:" + str(building))
                    code = row[1]
                    print("Code: " + str(code))

                    print("%f seconds" % (time.time() - startTime))

                    # Conditional statements based on facility code.
                    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","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":

                        # 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","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":

                        # 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","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":

                        # 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",                                                          "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":

                        # Create Layer object
                        lyr = arcpy.mapping.ListLayers(mxd, "Meter", df)[0]
                        print lyr

                        # Select building by BO number.
                        arcpy.SelectLayerByAttribute_management("Meter",
                                                                "NEW_SELECTION",                                                                   "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":

                        # Create Layer object
                        lyr = arcpy.mapping.ListLayers(mxd, "Survey", df)[0]
                        print lyr

                        # Select building by BO number.
                        arcpy.SelectLayerByAttribute_management("Survey",
                                                                "NEW_SELECTION","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

        print("%f seconds" % (time.time() - startTime))

    def refresh(self):
        pass

class Results(object):
    """Implementation for EAD_addin.Results (ComboBox)"""
    def __init__(self):
        self.items = []
        self.editable = True
        self.enabled = True
        self.dropdownWidth = '1234567890123456789012345678901234567890'
        self.width = '1234546789012345467890'

    def onSelChange(self, selection):
        startTime = time.time()

        # Set current mxd and dataframe.
        mxd = arcpy.mapping.MapDocument("CURRENT")
        df = arcpy.mapping.ListDataFrames(mxd, "")[0]


        # Make TableView
        env.workspace = r"O:\\PATH\PATH\.sde"
        env.overwriteOutput = True
        eadFacil = "SDE.sewerman.tblEADFacilities"
        table_view = arcpy.MakeTableView_management(eadFacil, "resultsView", "Address = '" + selection + "'")
        print(table_view)

        # Create summary statistics table to exclude duplicate facilities- get first occurrence of "ID"
        summary = arcpy.Statistics_analysis(table_view,
                                            r"in_memory\summaryTable",
                                            [["ID", "FIRST"],
                                             ["ADDRESS", "COUNT"],
                                             ["BO", "COUNT"],
                                             ["Factype", "COUNT"]],
                                            ["ADDRESS", "BO", "Factype"])

        result = arcpy.GetCount_management(summary)
        count = int(result.getOutput(0))
        print("Facility count: " + str(count))

        with arcpy.da.SearchCursor(summary, ["BO", "Factype"]) as cursor:
            for row in cursor:
                building = row[0]
                print ("building number:" + str(building))
                code = row[1]
                print("Code: " + str(code))

                # Conditional statements based on facility code.
                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","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":

                    # 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","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":

                    # 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","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":

                    # 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","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":

                    # Create Layer object
                    lyr = arcpy.mapping.ListLayers(mxd, "Meter", df)[0]
                    print lyr

                    # Select building by BO number.
                    arcpy.SelectLayerByAttribute_management("Meter",
                                                            "NEW_SELECTION","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":

                    # Create Layer object
                    lyr = arcpy.mapping.ListLayers(mxd, "Survey", df)[0]
                    print lyr

                    # Select building by BO number.
                    arcpy.SelectLayerByAttribute_management("Survey",
                                                            "NEW_SELECTION","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

        print("%f seconds" % (time.time() - startTime))

    def onEditChange(self, text):
        pass

    def onFocus(self, focused):
        # # Set current mxd and dataframe.
        # mxd = arcpy.mapping.MapDocument("CURRENT")
        # df = arcpy.mapping.ListDataFrames(mxd, "")[0]

        # # Empty list that will receive duplicate elements.
        # first_list = []
        # Empty list that will be used for combobox with duplicates removed.
        self.items = []
        #
        # # List layers
        # table_list = arcpy.mapping.ListTableViews(mxd, "resultsView", df)
        # print(table_list)
        # # Loop through layer list with one element.
        # for table in table_list:
        #     # Populate self.items for combobox with elements generate from search cursor.

        with arcpy.da.SearchCursor(r"in_memory\summaryTable", ["Address"]) as cursor:
            for row in cursor:
                self.items.append(row)
                print row
        # for i in first_list:
        #     if i not in self.items:
        #         self.items.append(i)
        print(self.items)

    def onEnter(self):
        pass

    def refresh(self):
        pass
6

As mentioned in the documentation, you can refer to other 'types' by using the appropriate ID.
This is what you set in the wizard when creating the combo-box, button, etc. and you can change it by editing the config.xml file in the root directory of your addin source.

A really simple example that clears a combo-box list when the user presses a button:

import arcpy
import pythonaddins

class ButtonClass1(object):
    """Implementation for test_addin.button (Button)"""
    def __init__(self):
        self.enabled = True
        self.checked = False
    def onClick(self):
        combobox.items = []

class ComboBoxClass2(object):
    """Implementation for test_addin.combobox (ComboBox)"""
    def __init__(self):
        self.items = ["item1", "item2"]
        self.editable = True
        self.enabled = True
        self.dropdownWidth = 'WWWWWW'
        self.width = 'WWWWWW'

In your case, you would want to have Results.items = [] somewhere in the implementation of the onEditChange method of the Facility class:

def onEditChange(self, text):
        Results.items = []
        global query
        query = text
        print(query)
        ...

It's also worth noting that the automatically generated source code has the ID in the docstring (comment) of the class. In your example, """Implementation for EAD_addin.FacililtySearch (ComboBox)""", EAD_addin is the namespace and FacilitySearch is the ID that you can use to refer to the facility search combo-box itself.

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.