[GIS] Using ArcPy to copy layer in ArcMap TOC, rename copy, and paste back to TOC

arcgis-10.0arcmaparcpylayerstable of contents

How do I make a copy of a layer in the ArcMap TOC (passed to my script as a Feature Layer), assign the copy a new name, set a definition query on it, and then add the copied Feature Layer back into the TOC?

This is easily achieved manually via the ArcMap interface, but I'm yet to discover how to achieve this programatically.

My application of this is to take an input layer, then effectively split the layer by attributes in a specified field, creating a new Feature Layer for each unique attribute in the input. Thus the number of output Feature Layers will vary depending on the input data. All output Feature Layers will be added to a specified group layer.

The following code almost achieves this, but if I then try and change the name of the copied layer (via ArcPy), the names of both the original layer in the TOC, and the copy of that layer (now in the new group layer) are changed. Note that this code also includes adding of a new Group Layer to the TOC (using a template LYR file on disc), into which the copied layer is inserted)

mxd = arcpy.mapping.MapDocument('CURRENT')
df = arcpy.mapping.ListDataFrames(mxd, dataFrameName)[0]
inputLayer = arcpy.mapping.ListLayers(mxd, inFC, df)[0] #this is the Layer from the TOC     specified by the user

#Add empty group layer to TOC
groupLayer = arcpy.mapping.Layer("<File path to LYR file>\EmptyGroupLayerTemplate.lyr")
arcpy.mapping.AddLayer(df, groupLayer, "TOP")

targetGroupLayer = arcpy.mapping.ListLayers(mxd, "EmptyGroupLayerTemplate", df)[0]

#Add copy of feature layer into the new Group Layer
arcpy.mapping.AddLayerToGroup(df, targetGroupLayer, inputLayer, "AUTO_ARRANGE")

I have tried ensuring that I get a reference to only the new copy of the layer, by ensuring the layer name is proceeded by the group layer name:

for layer in layerList:
  if layer.isGroupLayer and layer.name == groupLayer.name:
    for subLayer in layer:
      if subLayer.name == inputLayer.name:
        #Change this layers name
        subLayer.name = outName
        arcpy.RefreshTOC()

..and I have also tried:

for lyr in arcpy.mapping.ListLayers(mxd):
  #If layers long name contains the new grouplayer name..
  if lyr.longName.find(groupname + "\\") != -1:
    #'-1' when string not found       
    inputLayerFullName = groupname + "\\" + inputLayerName       
    if  lyr.name == inputLayerFullName:
      lyr.name = "NewLayerName" 
      arcpy.RefreshTOC()

…both these techniques do rename the copied layer, but they ALSO rename the original layer, regardless of where it is in the TOC.

It feels like I am working with a reference type rather than a value type in this respect, but I cannot see how to work with the layer object in another way. Seems that the issue lays with the fact that both Feature Layers (in the TOC) have the same name; reference one by name, yet both get updated.

I've tried making a copy of the input Feature Layer, assigning the copy a new name, then add this to the TOC, but the code errors executing AddLayerToGroup():

arcpy.MakeFeatureLayer_management(inputLayer, "TestFeatureLayer")
arcpy.mapping.AddLayerToGroup(df, targetGroupLayer, "TestFeatureLayer", "AUTO_ARRANGE")

I'm yet to try saving the original Feature Layer to a LYR file on disc, then changing the properties of the LYR file, and adding that back into the TOC, but I'd prefer not to go down this route as I dont really want to save any data to disc. After all, this operation is achieved within the ArcMap GUI without saving to disc, so it should be possible via Arcpy (or ArcObjects if necessary) too.

I am using ArcGIS 10.0.

Best Answer

 def CopyPasteLayer(CopyLayer, PastedLayerName):
 mxd = arcpy.mapping.MapDocument("Current")
 df = arcpy.mapping.ListDataFrames(mxd)[0]
 CopyLayerList = [arcpy.mapping.Layer(str(CopyLayer))]
 for CopyLayer in CopyLayerList:
     CopyLayer.name = str(PastedLayerName)
     arcpy.mapping.AddLayer(df, CopyLayer, "AUTO_ARRANGE")
 arcpy.RefreshTOC()
 arcpy.RefreshActiveView()

'CopyLayer' argument is the name of the layer as it appears in the ToC which you want to make a copy of

'PastedLayerName' argument is the name of the layer as you want it to appear in the ToC once pasted.

Use Example:

CopyPasteLayer("SitesToCopy", "PastedSites")

Keep in mind that this is all happening the the ToC and thus in-memory, so if you close your ArcMap session, that pasted layer will be lost unless you save it.

Related Question