ArcGIS 10: Is there a way to Remove All Joins with Python?

6255
4
09-16-2010 04:35 PM
JoeVondracek
New Contributor III
Is there some method of removing all Joins on a layer with Python?  The arcpy.RemoveJoin_management tool requires a named Join and it doesn't appear possible to wildcard the name.  It seems strange that there isn't some way to perform a Remove All Joins within Python.

Alternatively, is there a way to determine the names of all of the Joins on a layer with Python?  If I were able to get a list of those, I could iteratively remove them, one by one.
4 Replies
StevePeaslee
Occasional Contributor
Below is a 9.2 python function that I've used on featurelayer joins. Not the perfect solution, like you I wish there was a way to list all join objects on a layer or table. I don't have 10 installed yet, so  there may be some changes required to get it to run. I know that 9.3 and 10 will handle the list of fields differently (get rid of the .Next and change While loop to For loop) . Also you will need to import 'traceback' or remove the reference to it in the exception handling.

Hopefully this will give you some ideas in case no one else has a proper solution.


-Steve

## =======================================================================
def RemoveJoins(theInputTable, theWildcard):
    ## Remove any joined tables matching wildcard string
   
    try:
        theJoinList = []
        theDesc = gp.Describe(theInputTable)
        if theDesc.DataType.upper() == "FEATURELAYER":
            theFC = theDesc.Featureclass.Name.replace(".shp","")
            #AddMsgAndPrint("\nFeatureclass name for input = " + theFC + "\n", 0)

        else:
            AddMsgAndPrint("Error." + theInputTable + " is not a featurelayer", 2)
            return False
       
        theFields = theDesc.Fields
        theField = theFields.Next()

        while theField:
            FullName = theField.Name
            nameList = gp.ParseFieldName(FullName).split(",")
            #AddMsgAndPrint("    Qualified field name = " + FullName, 0)
            theFieldName = nameList[3]
            theTableName = FullName[0:-(len(theFieldName))]
           
            if theTableName != theFC and not theTableName in theJoinList:
                # Found join, but only remove it if it matches wildcard
                if theWildcard == "" and theTableName != " ":
                    theJoinList.append(theTableName)
                    #AddMsgAndPrint("    Removing join: " + theTableName, 0)
                    gp.RemoveJoin_management(theInput, theTableName)

                elif theTableName.startswith(theWildcard):
                    theJoinList.append(theTableName)
                    #AddMsgAndPrint("    Removing join: " + theTableName, 0)
                    gp.RemoveJoin_management(theInput, theTableName)

            theField = theFields.Next()
           
        return True
       
    except:
        AddMsgAndPrint("Exception in RemoveJoins", 2)
        tb = sys.exc_info()[2]
        tbinfo = traceback.format_tb(tb)[0]
        pymsg = tbinfo + "\n" + str(sys.exc_type)+ ": " + str(sys.exc_value)
        AddMsgAndPrint(pymsg, 2)
        return False
JoeVondracek
New Contributor III
Thanks, Steve!  I took what you posted and modified it to work in ArcGIS 10 and do what I wanted.  Following is what I came up with, in case it's of any use to others.

(Incidentally, in your calls to RemoveJoin_management, you have "theInput", but I believe that should be "theInputTable".)

## =======================================================================
def RemoveAllJoins(theInputTable):
## Remove all joined tables.

    try:
        arcpy.AddMessage("Remove All Joins from " + theInputTable)
        theJoinList = []
        theDesc = arcpy.Describe(theInputTable)
        if theDesc.DataType.upper() == "FEATURELAYER":
            # If it's a shapefile, remove the extension from the name.
            theFC = theDesc.Featureclass.Name.replace(".shp","")
        else:
            arcpy.AddMessage("\n  ERROR: " + theInputTable + " is not a feature layer!\n")
            return False

        # Look at the fields for this layer.  A full field name includes
        # the table name, i.e., TABLE.FIELD, where TABLE matches the name
        # of the feature class.  However, if there is a Join on the table,
        # the joined field names will be like JOINTABLE.FIELD, so we can
        # look for those other table names which represent Joins.
        theFields = theDesc.Fields
        for theField in theFields:
            FullName = theField.Name
            # Get rid of spaces in field name components and split them into a list.
            nameList = arcpy.ParseFieldName(FullName).replace(" ","").split(",")
            theTableName = nameList[2]
            if theTableName != theFC and not theTableName in theJoinList:
                # Keep track of Joins that were removed; remove only once.
                theJoinList.append(theTableName)
                arcpy.AddMessage("  Removing join: " + theTableName)
                arcpy.RemoveJoin_management(theInputTable, theTableName)

        return True

    except Exception as e:
        arcpy.AddError(e.message)
        return False 
RichardChase1
New Contributor
Nice Joe, I took that code and made it run from the toolbox.  Just added this script to the toolbox and it removed all joins in my map.  Saved me at least an hour of finding the rogue joins I had forgotten about in the 50+ layers in my map.


# ---------------------------------------------------------------------------
# RemoveJoins.py
# ---------------------------------------------------------------------------

import arcpy,sys
from arcpy.mapping import *

## =======================================================================
def RemoveAllJoins(theInputTable):
## Remove all joined tables.

    try:
        arcpy.AddMessage("Remove All Joins from " + theInputTable.name)
        theJoinList = []
        theDesc = arcpy.Describe(theInputTable)
        if theDesc.DataType.upper() == "FEATURELAYER":
            # If it's a shapefile, remove the extension from the name.
            theFC = theDesc.Featureclass.Name.replace(".shp","")
        else:
            arcpy.AddMessage("\n  ERROR: " + theInputTable + " is not a feature layer!\n")
            return False

        # Look at the fields for this layer.  A full field name includes
        # the table name, i.e., TABLE.FIELD, where TABLE matches the name
        # of the feature class.  However, if there is a Join on the table,
        # the joined field names will be like JOINTABLE.FIELD, so we can
        # look for those other table names which represent Joins.
        theFields = theDesc.Fields
        for theField in theFields:
            FullName = theField.Name
            # Get rid of spaces in field name components and split them into a list.
            nameList = arcpy.ParseFieldName(FullName).replace(" ","").split(",")
            theTableName = nameList[2]
            if theTableName != theFC and not theTableName in theJoinList:
                # Keep track of Joins that were removed; remove only once.
                theJoinList.append(theTableName)
                arcpy.AddMessage("  Removing join: " + theTableName)
                arcpy.RemoveJoin_management(theInputTable, theTableName)

        return True

    except Exception as e:
        #arcpy.AddError(e.message)
        return False

mxd = arcpy.mapping.MapDocument("CURRENT")
df = arcpy.mapping.ListDataFrames(mxd, "Layers")[0]

for item in df:
    RemoveAllJoins(item)
curtvprice
MVP Esteemed Contributor

Here's a little function to remove all joins. Also see (and vote up!) Remove all joins programatically

def RemoveAllJoins(tbl):
    """Remove all joins from a layer or table view"""
    flds = [f.name for f in arcpy.ListFields(tbl)]
    wk = os.path.dirname(arcpy.Describe(tbl).catalogPath)
    joins = [arcpy.ParseFieldName(f, wk).split(", ")[-2] for f in flds]
    joins = list(set(joins)) # unique the list
    if joins[0] == "(null)":
        print("no join active")
    else:
        # remove base table name from list and remove all joins
        joins.remove(arcpy.Describe(tbl).baseName)
        for j in joins:
            arcpy.RemoveJoin_management(tbl, j)
            print("Removed join {}".format(j))
    return
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos