1

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.

5
  • 1
    Is there a particular reason you want to not write to disc?
    – gm70560
    May 9, 2013 at 16:56
  • I can understand the "not write to disc" requirement (see my Answer) in point 1 but I am unclear why you would want/expect data in in_memory workspaces to persist between ArcMap/ArcPy sessions (your point 2).
    – PolyGeo
    May 9, 2013 at 21:04
  • I don't want to write to disc as I don't want to create new Feature Classes unnecessarily. The application I have in mind for this would result in the generation of many Feature Classes each time the script were run; I think that would be a very messy solution. The ArcMap functionality I describe in my question is exactly what I want to achieve (but programatically), and as that workflow manages to not write to disc, I feel sure there must be a way to achieve this programatically.
    – user17992
    May 10, 2013 at 8:31
  • " I am unclear why you would want/expect data in in_memory workspaces to persist between ArcMap/ArcPy sessions (your point 2). – PolyGeo". ....no, I agree, and I see this part of my question is a little confusing. I was clutching at straws a bit, trying to think how a new Feature Layer could be added. On further thinking about this, a Feature Layer is more a property of the map document, as that is the only domain it exists in.
    – user17992
    May 10, 2013 at 8:38
  • If I understand your question, you are just trying to (programmatically) create a new layer that still references the original layers' underlying source and just apply a new def query, symbology, etc to the new layer? You want to avoid creating a new file on disk, correct? Jul 9, 2013 at 19:22

4 Answers 4

4
 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.

1
  • Because the modification to the name property takes place before the AddLayer call, your code will result in the same undesired consequence as @User17992 - both the original and duplicate copy will be renamed Nov 11, 2014 at 14:40
1

Just encountered the same problem, this time wanting to duplicate layers, but not being able to use the geoprocessing tool and a temporary LYR file because this route does not preserve all the elements of the layer (in my case the display format settings for fields in the attribute table). My conclusion is that you have to use an extension of the code proposed by @MrBubbles with the following logic:

  1. Create a layer object referencing a layer from the data frame by name
  2. Modify that layer's name
  3. Add a copy of that layer back to the data frame - this copy is now independent of the original layer
  4. Modify the layer object's name property again to return it to it's original value (and probably destroy the object)
  5. (optional) Create a new layer object referencing the duplicated layer in the data frame (from step 3) by its modified name

Steps 1-3 are covered by @MrBubbles in his answer. Modified code below:

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

I've just tinkered around with python and I did this, is this what you want?

arcpy.env.addOutputsToMap = False
mxd = arcpy.mapping.MapDocument('CURRENT')
df = arcpy.mapping.ListDataFrames(mxd, "Inset Map")[0]

# Create a featurelayer with just 1 polygon in it and call it wales
res = arcpy.MakeFeatureLayer_management("Coastline","wales","FID = 3")

# Add to map
arcpy.mapping.AddLayer(df,res.getOutput(0))

I then ran your name changing code and it changed only the wales layer name, I have to admit I did not test it on data in a grouplayer.

0

I'm not sure if you solved your problem but I was having the same problem. I think using a layer file is the only way to solve this problem. First save a layer file with the correct source and symbology that you want. Create a layer of it, change the layer name and other properties you want and then add it to the map. You'll have to create a new layer from the layer file every time before adding it to the map but it worked for me. Something like this.

mxd = arcpy.mapping.MapDocument("CURRENT")
df = arcpy.mapping.listDataFrames(mxd)[0]
layer_names = ["test1", "test2", "test3"]
for layer in layer_names:
    lyr = arcpy.mapping.Layer("path to layer file\Layer Test.lyr")
    lyr.name = layer
    arcpy.mapping.AddLayer(df, lyr)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.