1

I would like to automate the importation of a directory as a hierarchy of group layers in the Table Of Content of ArcMap with Arcpy. I already saw and adapt these posts and scripts :

Unfortunatelly, each code had only one level depth, so there’s no group layer(s) into another group layer. In other words, there’s only one group layer per directory and the hierarchy of the directory isn’t preserve. The expected result is shown in the images below.

expected result

Here's my code:

import arcpy
import os


folder =r'C:' #root folder
template_group_layer = r'C:' #empty layer
mxd=arcpy.mapping.MapDocument("CURRENT")
df = arcpy.mapping.ListDataFrames(mxd)[0]


groups={}
for path, dirs, files in arcpy.da.Walk(folder): #search in directory and create group layer

for d in dirs:
    lyr=arcpy.mapping.Layer(template_group_layer) #add empty group layer to ArcMap
    lyr.name=d 
    arcpy.mapping.AddLayer(df,lyr)
    groups[d]=arcpy.mapping.ListLayers(mxd,d,df)[0]

for f in files: #select files that are shapefiles and insert them in their groups as the directory architecture
    fp=os.path.join(path,f)
    dsc=arcpy.Describe(fp)
    print dsc
    lyr=None
    view=None
    if dsc.dataType == 'ShapeFile':
        lyr=arcpy.management.MakeFeatureLayer(fp,os.path.basename(fp))[0] #edit 1 - remove layer in dataframe to prevent duplicate
        arcpy.mapping.RemoveLayer(df, lyr)
        print lyr
    else:continue

    if path==folder and lyr:
        lyr.visible=False
        arcpy.mapping.AddLayer(df,lyr)
    else:
        d=os.path.basename(path)
        arcpy.mapping.AddLayerToGroup(df, groups[d], lyr, "BOTTOM")

Current result

enter image description here

1
  • 1
    Please include a code snippet to illustrate how close you are to solving this, and where you are currently stuck.
    – PolyGeo
    Feb 3, 2017 at 11:07

1 Answer 1

1

I've taken a slightly different approach as I don't iterate all the data through one run constructing a lookup dictionary. Instead, I am going through every folder and adding layers on my way. I've added some additional comments for clarity and I hope they will make it easier for everyone to follow.

This code should operate on folders with unlimited number of nested folders, doesn't matter whether it is just two as you have or a hundred. I've added a screenshot to illustrate the results.

Code

import os
import arcpy.mapping as mp
env = r'C:\GIS\Temp\GISSE'
mxd = mp.MapDocument(r"C:\GIS\Desktop\gisse_mxd.mxd")
df = mp.ListDataFrames(mxd)[0]

lyr_path = r'C:\GIS\Temp\NewEmptyGroupLayer.lyr'
new_empty_group_layer = mp.Layer(lyr_path)

walk = arcpy.da.Walk(env, datatype=None, type="All")
for dirpath, dirnames, filenames in walk:
    print('-'*30)
    print(dirpath)
    if dirnames:
        for dirname in dirnames:
        #for each folder found create a group layer
            #if group layer already exists, add a new group layer to the parent group layer;
            #else create a new one
            group_lyr_name = os.path.basename(dirpath)
            if mp.ListLayers(mxd, group_lyr_name): #group layer already exists
                mp.AddLayerToGroup(df, mp.ListLayers(mxd, group_lyr_name)[0],
                                   new_empty_group_layer, add_position='BOTTOM')
            else: #doesn't exist, create a new one add to the bottom
                mp.AddLayer(df, new_empty_group_layer, add_position='BOTTOM')

            #rename the group layer to the folder name
            lyr = mp.ListLayers(mxd,'New Group Layer')[0]
            lyr.name = dirname

    print("Directory names ->", dirnames)
    print("Filenames ->", filenames)
    if filenames: #if there are any shapefiles in the folder
        for filename in filenames:

            #get the folder name where the shapefiles are stored
            base_folder = os.path.basename(dirpath)
            print('Where the shapefile is stored ->', base_folder)

            #get the group layer with the name of the folder where the shapefile is stored
            group_lyr = mp.ListLayers(df, base_folder)[0]
            print("Group layer name ->", group_lyr)

            #add layer to group layer
            arcpy.env.workspace = dirpath

            out_lyr_name = filename.split('.')[0] + '_shp' #to avoid confusion with the file path and fl name
            shp_feat_lyr = arcpy.MakeFeatureLayer_management(in_features=filename,
                                                             out_layer=out_lyr_name).getOutput(0)
            print("Feature layer name ->", shp_feat_lyr)

            #if the group layer exists, add feature layer to this group layer
            if mp.ListLayers(mxd, wildcard=base_folder):
                mp.AddLayerToGroup(df, group_lyr, shp_feat_lyr, add_position='AUTO_ARRANGE')
            else: #the shapefiles is stored in the root, add to the root group layer
                mp.AddLayer(df, shp_feat_lyr, add_position='AUTO_ARRANGE')

            #renaming the layer to have `.shp` at the end
            lyr = mp.ListLayers(mxd,out_lyr_name)[0]
            lyr.name = filename
mxd.save()

Results in ArcMap

enter image description here

2
  • Np! Please comment back whether the code works as expected for you. Feb 6, 2017 at 14:31
  • I will do it, but I need to resolve others little bugs before.
    – tantmieux
    Feb 10, 2017 at 9:40

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.