[GIS] Adding group layer, renaming it from folder name, then adding layers to it from that folder, using ArcPy/Python

arcgis-10.1arcpygroup-layerpythonpython-2.7

I am trying to use os.walk to go through a directory tree, pull out all the .shp files in it, create a grouplayer in the mxd, rename the grouplayer the folder name, then add the layers from that folder to the group. This is because I have a lot of folders with files in them that represent geologic formations and they don't mean anything once seperated from the name of the formation.

From what I read you can't just add a blank group layer in an mxd from python without first creating a blank one and adding that. The problem starts at the for group_name in rename_group_layer loop. It doesn't even make it through to the print group_name test. Basically it just falls out of the loop from what I can tell.

Then I need to figure out how to add the layers from the folder into the renamed group layer. I have two lines commented out that I think are a start, but I haven't gotten it to go through the renaming loop yet. It will rename the first "New Group Layer" if I put that line above the loop to the correct folder name. I am pretty new to python so any help you can give would be greatly appreciated.

import os
import arcpy

# Set workspace environment to a folder
WS = r'c:\test_define\Appalachian Basin'
arcpy.env.workspace = WS

mxd = arcpy.mapping.MapDocument(r"c:\test_define\test_python_add3.mxd")
df = arcpy.mapping.ListDataFrames(mxd, "layers")[0]

print ("#") *80
for (path, dirs, files) in os.walk(WS):
    for name in files:
        if name.endswith(".shp"):
        print path
           print "^^^^^^^^^^^^^^^^^^ path variable"

            try:
                layers = arcpy.mapping.ListLayers(mxd)
                for layer in layers:
                    if layer.isGroupLayer and layer.name == os.path.basename(path):
                        newLayer = arcpy.mapping.Layer(os.path.join(path, name))
                        arcpy.mapping.AddLayerToGroup(df, layer, newLayer, "BOTTOM")
                    else:
                        groupLayer =                       arcpy.mapping.Layer(r"c:\test_define\empty_group_layer.lyr")  
                        arcpy.mapping.AddLayer(df, groupLayer, "BOTTOM")

                        layers = arcpy.mapping.ListLayers(mxd)
                        for layer in layers:
                            if layer.isGroupLayer and layer.name == "New Group Layer":
                                layer.name = os.path.basename(path)

                        newLayer = arcpy.mapping.Layer(os.path.join(path, name))
                        arcpy.mapping.AddLayerToGroup(df, layer, newLayer, "BOTTOM")

#mxd.save()


# print messages when the tool runs successfully
            print(arcpy.GetMessages(0))
            #print ("+") *50
        except arcpy.ExecuteError:
            print(arcpy.GetMessages(2))

        except Exception as ex:
            print(ex.args[0])

mxd.saveACopy(r"c:\test_define\test.mxd")

Best Answer

This should work; it worked for me. This will give you a group layer named by the folder and a layer with the name of the shapefile. I built off what artwork21 posted.

import os
import arcpy

WS = r'c:\test_define'
arcpy.env.workspace = "in_memory"

mxd = arcpy.mapping.MapDocument(r"c:\test_define\test_python_add2.mxd")
df = arcpy.mapping.ListDataFrames(mxd, "Layers")[0]

for (path, dirs, files) in os.walk(WS):
    for name in files:
        if name.endswith(".shp"):

            groupLayer = arcpy.mapping.Layer(r"c:\test_define\empty_group_layer.lyr")  
            arcpy.mapping.AddLayer(df, groupLayer, "BOTTOM")

            layers = arcpy.mapping.ListLayers(mxd)
            for layer in layers:
                if layer.isGroupLayer and layer.name == "New Group Layer":
                    layer.name = os.path.basename(path)

            newLayer = arcpy.mapping.Layer(os.path.join(path, name))
            arcpy.mapping.AddLayerToGroup(df, layer, newLayer, "BOTTOM")

mxd.save()

You have to make the shapefiles into layers and use AddLayerToGroup. If you want a single group layer for each folder you can recycle this code and modify the os.walk to check for folders with .shp's and go from there. Although, I would recommend trying to contain all these shapefiles into a geodatabase with a proper naming structure and metadata to fit your needs.

To elaborate on the nonrepeating,

import arcpy
import os 

WS = r'c:\test_define'
arcpy.env.workspace = "WS"
mxd = arcpy.mapping.MapDocument(r"c:\test_define\test_python_add2.mxd")
df = arcpy.mapping.ListDataFrames(mxd, "Layers")[0]
groupLayer = arcpy.mapping.Layer(r"c:\test_define\empty_group_layer.lyr")

for (path, dirs, files) in os.walk(WS):
    for name in files:
        if name.endswith(".shp"):

            layers = arcpy.mapping.ListLayers(mxd)
            name_list = []
            for layer in layers:
                if layer.isGroupLayer:
                    name_list.append(layer.name)

            if os.path.basename(path) not in name_list:
                arcpy.mapping.AddLayer(df, groupLayer, "BOTTOM")
                layers = arcpy.mapping.ListLayers(mxd)
                for layer in layers:
                    if layer.isGroupLayer and layer.name == "New Group Layer":
                        layer.name = os.path.basename(path)
                        newLayer = arcpy.mapping.Layer(os.path.join(path, name))
                        arcpy.mapping.AddLayerToGroup(df, layer, newLayer, "BOTTOM")

            if os.path.basename(path) in name_list:
                layers = arcpy.mapping.ListLayers(mxd)
                for layer in layers:
                    if layer.isGroupLayer and layer.name == os.path.basename(path):
                        newLayer = arcpy.mapping.Layer(os.path.join(path, name))
                        arcpy.mapping.AddLayerToGroup(df, layer, newLayer, "BOTTOM")


mxd.save()

This will check to see if a group layer already exists and will add to it, if so. Else, it will create a new group layer and add the layer.

Related Question