Python Add-In Button Issues

12162
28
08-11-2015 01:16 PM
CoyPotts1
Occasional Contributor III

@

I'm tagging Rebecca because of the conversation here: Custom toolbar that contains Python Scripts

I have been playing with the Python Add-In Wizard, and I have created a toolbar with some menus and buttons.  I am having trouble getting the buttons to work, though.  I've followed Rebecca's instructions (here: Python add-ins vs. .NET add-ins?​), as well as the attached PDF to try and use an existing python script within my toolbox, but the button just shows up as missing when I install the add-in and run ArcMap.  I've even tried pasting the entire code from the script directly into the onClick function, and that just does the same thing.

Is this a common problem?  Is this indicative of a common issue, or could it be a vague error that would be harder to diagnose...?  I read somewhere that the missing designation could mean that there is some sort of syntax error in the code, but the scripts work on their own...just not whenever I try to associate them with a button on the custom add-in toolbar.

Thanks you!

28 Replies
RebeccaStrauch__GISP
MVP Emeritus

Hi Coy,

If you are getting the "null-missing" for you button, in your <project>_addin.py file,   check to make sure your quotes are balanced, and the same type.  I had a set of striat quotes on one side some text, and the curly type on the other side, and that gave me an issue on the toolbar I'm currently work on.  Drove me nuts for a while.

If you can post that file (see Posting Code blocks in the new GeoNet​ ) , it may help to see if there is anything obvious.  The missing button, per esri support, means syntax error....pretty generic.  But more sets of eyes might help.

CoyPotts1
Occasional Contributor III

This is the python file with the code within it.  Again, it is a direct copy from the working script that we use daily, so I don't think it is a syntax error, unless there is some functionality that needs to change between stand-alone scripts and add-ins.

import arcpy
import pythonaddins
import os
import arcpy.mapping as map
from arcpy import env
mxd = map.MapDocument("CURRENT")

class map_to_kml(object):
    """Implementation for map_to_kml.button (Button)"""
    def __init__(self):
        self.enabled = True
        self.checked = False
    def onClick(self):

        # Apply Symbology Layer file  

        # Set local variables
        inputLayer = r'Entire Coverage Area\Fiber Segments'   
        symbologyLayer = r'\\extenet.local\dfs\Network-Planning-GIS\1)Documentation\ArcGIS_Files\4)Symbology_Layer_Files\Fiber Segments (KMZ).lyr'  

        # Execute the ApplySymbologyFromLayer tool
        arcpy.ApplySymbologyFromLayer_management (inputLayer, symbologyLayer)

        # Save the map  
        mxd.save()

        # Map to KML tool  

        # Set local variables  
        df = arcpy.mapping.ListDataFrames(mxd)[0].name
        mapName = str(mxd.filePath).split('\\')[-1:][0][:-4]
        filepath1 = str(mxd.filePath)[:79] + mapName + "/6)Deliverables/"
        version = arcpy.GetParameterAsText(0)
        outputKML = filepath1 + mapName + " " + version + '.kmz'
        extent = 'Same as layer Fiber Segments'  

        # Execute MapToKML tool 
        arcpy.MapToKML_conversion(mxd.filePath, df, outputKML, '', '', '', extent,'', '', '')


        # Apply Symbology Layer file

        # Set local variables  
        inputLayer = r'Entire Coverage Area\Fiber Segments'    
        symbologyLayer = r'\\extenet.local\dfs\Network-Planning-GIS\1)Documentation\ArcGIS_Files\4)Symbology_Layer_Files\Fiber Segments.lyr'  

        # Execute ApplySymbologyFromLayer tool
        arcpy.ApplySymbologyFromLayer_management (inputLayer, symbologyLayer)

Here is the python file just referencing the existing script:

import arcpy
import pythonaddins
import os
relPath = os.path.dirname(__file__)

class map_to_kml(object):
    """Implementation for map_to_kml.button (Button)"""
    def __init__(self):
        self.enabled = True
        self.checked = False
    def onClick(self):
        toolPath = relPath + r'\ExteNet Systems Toolset.tbx'
        pythonaddins.GPToolDialog(toolPath, 'Map to KML1')

I made sure that the referenced tool is using relative path names, and the toolbox is in the install folder for the add-in.  I tried this with just about every variation of the tool name I could think of.  I used the no space version, I used the ".py" afterwards. I also tried the os.startfile() method with a direct link to the tool instead of concatenated as shown above.

0 Kudos
RebeccaStrauch__GISP
MVP Emeritus

The tool name in the  pythonaddins.GPToolDialog line definitely shouldn't have spaces.  Make sure you are taking the Name and not the Label

Also, for what it's work, I've pulled the ToolPath line to the top of the _addin.py file so I don't have to repeat it, for example.

import arcpy
import pythonaddins
import os
relPath = os.path.dirname(__file__)
toolPath = relPath + r"\CheckAndFixLinks.tbx"


class btnGDBInventory(object):
    """Implementation for GDBInventory_addin.button (Button)"""
    def __init__(self):
        self.enabled = True
        self.checked = False
    def onClick(self):
        pythonaddins.GPToolDialog(toolPath, "ListFGDBsize")

class btnFCInventory(object):
    """Implementation for FCInventory_addin.button (Button)"""
    def __init__(self):
        self.enabled = True
        self.checked = False
    def onClick(self):
        pythonaddins.GPToolDialog(toolPath, "FCInventoryReport")        

Does your script run ok outside the addin?  That should be checked first of course.  you answered that in the OP.

also, try double quotes instead of single toolpath and tools.  Shouldn't matter, but worth a try.

CoyPotts1
Occasional Contributor III

Thanks for the suggestions, Rebecca.

Modifying the toolbox to have no spaces, as well as moving it to the top of the script, didn't work.  On that note, however, shouldn't the tool still run when I use the actual code instead of referencing a script file?

I have tried with double and single quotes.  Neither has made a difference, so I'm thinking it's the error is related to something else.

Just as a test I re-saved the project so that the python script was back to the default that is auto-created.  I re-created the add-in and installed it again.  The buttons still show up as missing.  Why would they show up as missing if I haven't modified the original python add-in script...?  I would have thought that they would simply show up and do nothing as apposed to showing as missing.

*EDIT*

I went back and instead of leaving "pass" after each onClick, I added a simple MessageBox. The below code still gives buttons that show as missing.

import arcpy
import pythonaddins

class map_to_kml(object):
    """Implementation for map_to_kml.button (Button)"""
    def __init__(self):
        self.enabled = True
        self.checked = False
    def onClick(self):
        pythonaddins.MessageBox("This is a message box.", "Message Box", 0)

class osp_export(object):
    """Implementation for osp_export.button (Button)"""
    def __init__(self):
        self.enabled = True
        self.checked = False
    def onClick(self):
        pythonaddins.MessageBox("This is a message box.", "Message Box", 1)
0 Kudos
RebeccaStrauch__GISP
MVP Emeritus

Coy, just as another refernce, I found another one of my older post and fixed the python code that was messed up on the forum move.  Tip: Python Addin - getting custom tools/toolbox to work - GPToolDialog

The script should be able to run in the Toolbar in catalog/map, as you expect it to once in the addin.  If it doesn't run in the toolbar it probably won't in the adding.  So, make sure you have all the bugs out of the code first.  I use an Wing-Pro to do most of my testing (mine is a Catalog addin, not ArcMap, btw) so I have a good debug window, but any debugger should work.

Do you have your button icons in the Images folder?  And does your config.xml have the correct path and image names?  A snippet from my config.xml is below. notice there is an image="" tag

...
   <AddIn language="PYTHON" library="ChkandFixLinks_addin.py" namespace="ChkandFixLinks_addin">
        <ArcCatalog>
            <Commands>
                <Button caption="List FGDB" category="Repair Broken Resource utilities" class="btnGDBInventory" id="GDBInventory_addin.button" image="Images\databases.png" message="Select folder to walk thru" tip="Lists FGDB paths and disk size">
                    <Help heading="FGDBs">Select folder to search</Help>
                </Button>
                <Button caption="Inventory Feature Classes (all types)" category="Repair Broken Resource utilities" class="btnFCInventory" id="FCInventory_addin.button" image="Images\application_cascade.png" message="List all feature classes in folder" tip="List all feature classes in folder">
                    <Help heading="Feature Class Inventory">Select folder to inventory. Include coverages and tables</Help>
                </Button>
                <Button caption="List Broken Source Links" category="Repair Broken Resource utilities" class="btnListBrokenSources"
...

Using the widget is easier than messing with the config file,   I typically add a couple of extra dummy buttons when I'm stubbing out my addin with the wizard, and then modify them manually afterwords.  You have to make sure everything that needs to have certain tags match still do, and that you have unique names for others. Easier said than done sometimes. Look at an example is often easier, I can send you a copy so you can see how I have mine setup, if that will help.  The addin isn't complete, butt he setup works.

CoyPotts1
Occasional Contributor III

Looking at the link you provided, I don't see any differences between your code and what I have tried, or have pasted in my last response using a simple MessageBox to see if the button would actually work without any script reference or long code included in the onClick. 

Back when I was trying to create a custom toolbar in ArcMap and loading my scripts into the GP tools section of the customize menu for placement on that toolbar, the Map to KML example I've shown above worked just fine.  The issue was whenever I was finished editing the toolbar and would close/re-open ArcMap, the button for the tool would still be there, but the designated image that I selected was no longer there and nothing would happen when I clicked the button.  Since I couldn't get anything to work with using the easy custom toolbar creation within ArcMap, that's when I decided to try your add-in suggestion.  Long story short...the script would run just fine (tested many times) whenever I still had ArcMap open, but I would lose the functionality once I closed that ArcMap document.  The toolbar was saved to my Normal document too, because it would display no matter which document I opened.

I don't have any images associated with the buttons at this time.  I figured I would work that part out once I got the buttons to work.  Would that not allow the button to work with simply displaying text on the add-in toolbar, though?

You can definitely send me any samples that you may have.  I would appreciate taking a look for reference .  Is there a way of privately providing a contact email on here?

0 Kudos
IanBroad
New Contributor III

If you open a Command Prompt window (start, run, cmd) and type python and then import arcpy - do you get any errors?

cmd.PNG

0 Kudos
CoyPotts1
Occasional Contributor III

I got the following message.  If I open up Start > All Programs I have a Python 3.4 folder, and I also have Python27 and Python34 folders located on my C:, so I'm not really sure why it's not picking up Python.

0 Kudos
IanBroad
New Contributor III

Yeah, I think your Windows Environment Variables are the issue here.

You need to right click on My Computer and go to Properties, then click on the Advanced system settings, and then on the Advanced tab click on the Environment Variables button at the bottom.

Next, in the lower part of the window find the Variable that says Path and double click on it, and makes sure that the following paths are at the front of the Variable value list:

C:\Python27\ArcGIS10.2;C:\Python27\ArcGIS10.2\Scripts;C:\Python27\ArcGIS10.2\Lib;

(Verify that these paths exist and are in this location, of course. If you just upgraded to 10.3 like you mentioned below, you'll probably need to change the paths to ArcGIS10.3 instead of 10.2)

You'll then most likely need to restart.

After restarting, try doing the python and import arcpy from the Command Prompt again.

V.PNG