4

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")
PolyGeo
  • 65,136
  • 29
  • 109
  • 338
SStreisel
  • 41
  • 1
  • 5
  • Oh there is no error by the way. It runs to exit code 0 but just doesn't execute that loop. – SStreisel May 01 '13 at 16:28
  • You have a python27 tag which suggests you are using ArcGIS 10.1 or 10.1 SP1. If it is the latter you may want to consider using arcpy.da.Walk. Also, is there any chance that you can break that long first paragraph up into a series of steps to make it easier to digest? If you can include a question mark somewhere it should make the main focus of your Question more obvious too. – PolyGeo May 02 '13 at 10:38

3 Answers3

3

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.

gm70560
  • 1,402
  • 11
  • 17
  • To have nonreapting groupfiles: list the layers, and if the group layer is not present - make and add, else skip to AddLayerToGroup. – gm70560 May 02 '13 at 20:45
  • I am sorry. I just got back to this and made the changes you suggested. Thank you so much for your help. Forgive my ignorance and newness to this, but I am stuck on this "to have nonreapeating groupfiles" though. I am getting a new group for every file in the folder which makes sense after going over the code. You would have to put the list and the skip above the add grouplayer line correct? I am just struggling to figure out where this would go in the code. Again I appreciate all of your help. – SStreisel May 13 '13 at 17:31
  • I have updated my answer to incorporate the non-repeating issue. – gm70560 May 13 '13 at 21:25
  • With the new code you suggested GM it doesn't do anything. It just creates a blank MXD doc. the map document (mxd = c:\test_define\test_python_add3.mxd) is blank that its using to add these groups to. The group layer doesn't get created unless the first layers loop is false. So it doesn't create the first group layer to run the test on until after the test fails. Is it kicking it out of the loop because there is no layer to list? – SStreisel May 14 '13 at 18:25
  • How in the heck do you add a code snippet in here? – SStreisel May 15 '13 at 16:45
  • This still produces a blank mxd. I think its falling out of the for layers in layers loop under the name_list = [] because there are no layers in the mxd in the first run. – SStreisel May 15 '13 at 16:46
  • I don't know what to tell you. I ran it on a directory of three folders with 2 shapefiles each. I got a mxd with three group layers named with the folder name with the two shapefiles. – gm70560 May 15 '13 at 23:46
  • Interesting. I am using version 2.7 what version are you using? So it won't have an issue with checking a list for something if its blank and running a loop on for layer in layers if there are no layers in the listing? – SStreisel May 16 '13 at 14:31
  • it's making a new list at every instance of a .shp file. python2.7.2. – gm70560 May 16 '13 at 14:33
0

This is pretty bare bones but it'll get the job done. One thing to point out is that you can change a layer's name before you add it to the map document, so you don't have to ListLayers to find it in the TOC. The assumptions made by this code are:

  1. Every folder has at least one shapefile (otherwise you'll get some empty group layers)
  2. The folders have unique names
  3. You have an empty group layer saved as a .lyr file somewhere

It could be modified to deal with more complications, but should work for you as is.

import arcpy
import os

topfolder = r"c:\path\to\top\folder" #this one contains the folders full of shapefiles
mxd_path = r"c:\path\to\mapdocument.mxd"
grplyrpath = r"c:\path\to\blankgrouplyr.lyr"

mxd = arcpy.mapping.MapDocument(mxd_path)
df = arcpy.mapping.ListDataFrames(mxd)[0]   

for path, dirs, files in os.walk(topfolder):

    for d in dirs:
        grplyr = arcpy.mapping.Layer(grplyrpath)
        grplyr.name = d
        arcpy.mapping.AddLayer(df,grplyr,"BOTTOM")
        grplyrTOC = arcpy.mapping.ListLayers(mxd,grplyr.name,df)[0]

        for shp in os.listdir(os.path.join(path,d)):
            if not os.path.splitext(shp)[1] == ".shp":
                continue
            lyr = arcpy.mapping.Layer(os.path.join(path,d,shp)
            arcpy.mapping.AddLayerToGroup(df,grplyrTOC,bnd_grplayer,"BOTTOM")

mxd.save()
mr.adam
  • 3,224
  • 14
  • 26
0

You can get group names within map document by:

layers = arcpy.mapping.ListLayers(mxd)

for layer in layers:

    if layer.isGroupLayer and layer.name == "Group":
       newname = str(yourfoldername) 
       layer.name = newname

       mxd.save()
artwork21
  • 35,114
  • 8
  • 66
  • 134