Thursday 21 December 2017

ArcPy - find layers with joins

Here is a brute force script for finding layers with JOINs. As there doesn't seem to be a "hasJoin" property I just use arcpy.RemoveJoin_management which throws an exception if there is no join. This is script is only usefull for once off checks.


ArcMap 10.3


 # find (all) joins in MXD by removing them!  
 # usage: copy MXD and run script or run script and don't save MXD as all JOINS will be removed  
 # result will be a list of all layers where JOIN has been removed succesfully  
 import arcpy  
 mxd = arcpy.mapping.MapDocument("CURRENT")  
 layers = arcpy.mapping.ListLayers(mxd)  
 allJoins = ''  
 for layer in layers:  
   try:  
     arcpy.RemoveJoin_management (layer.name)  
     print("join removed: "+layer.name)  
     allJoins += '\n'+layer.name  
   # no join throws exception  
   except Exception as err:  
     print(err.args[0])  
 print(allJoins)  

Wednesday 20 December 2017

ArcPy - MoveLayer fails with "assert refe_c is not None, 'Did not find reference layer.'"

Just wanted to copy and paste all layers into new MXD file. Unfortunately order of layers in TOC is not retained. So I googled for script and found one - but MoveLayer failed with error message "assert refe_c is not None, 'Did not find reference layer.'". The post did not mention anything like that.

Solution in my case : for the reference layer a fresh reference is required. 

old: refLayer=moveLayer
new: refLayer = arcpy.mapping.ListLayers(mxdT, moveLayer.name, dfT)[0]  

ArcMap 10.3.1


Here is the script:


 # -*- coding: utf-8 -*-  
 # source code initially taken from: https://community.esri.com/thread/28042  
 # assumption : no layer groups  
 # my use case : copy and paste all layers into new MXD, layer order is not retained - run script to restore layer order  
 import arcpy  
 mxd_source = r"C:\temp\source1.mxd"  
 mxd_target = r"C:\temp\target.mxd"  
 mxdT = arcpy.mapping.MapDocument(mxd_target)  
 # assumption: only one DF  
 dfT = arcpy.mapping.ListDataFrames(mxdT, "")[0]  
 mxdS = arcpy.mapping.MapDocument(mxd_source)  
 # assumption: only one DF  
 dfS = arcpy.mapping.ListDataFrames(mxdS, "")[0]  
 #initialize refLayer with layer  
 refLayer = arcpy.mapping.ListLayers(mxdT,"",dfT)[0]  
 for layerSource in arcpy.mapping.ListLayers(mxdS,"",dfS):    
   c=layerSource.longName  
   d=layerSource.description  
   sourceLayer=c+d  
   print("processing layer in source: '" + sourceLayer+"'.")    
   for layerTarget in arcpy.mapping.ListLayers(mxdT,"",dfT):  
    a=layerTarget.longName  
    b=layerTarget.description  
    moveLayer= a+b     
    if sourceLayer==moveLayer:  
      print("moving layer:'"+moveLayer+"', reference layer: '"+refLayer.name+"'.")  
      moveLayer=layerTarget            
      arcpy.mapping.MoveLayer(dfT,refLayer,moveLayer, "After")       
      #get fresh layer reference - otherwise MoveLayer will fail next time:  
      refLayer = arcpy.mapping.ListLayers(mxdT, moveLayer.name, dfT)[0]             
      break  
 mxdT.save()  
 #arcpy.RefreshActiveView()  
 #arcpy.RefreshTOC()