1

I am looking for a way of counting the amount of layers within a group layer

I have an empty group layer inside my map and I am looking for a way of initiating a process if there are 0 layers inside the group layer. So for I have been listing layers inside layer. But if there is nothing inside .. there is nothing to loop through.

Is there a simple way to count the amount of sub layers inside a group ? For example I have a MXD with one empty group layer inside it. I want to count the amount of layers inside the group layer So far I am only able to access the layer like this

import arcpy
group = []
mxd = arcpy.mapping.MapDocument(r"C:\Users\jackw_000\Documents\mxd\layer_mapV2.mxd")
df = arcpy.mapping.ListDataFrames(mxd, "Layers")[0]
for lyr in arcpy.mapping.ListLayers(mxd, "my_group_layer", df):
     group.append(lyr)

print group

Returns ['My_group_layer']

When I print out the list it returns my_group_layer... . I am missing something.. ? A sub note , I am running this from IDLE , so at no time I am in seeing whats inside the TOC interface

closed as unclear what you're asking by PolyGeo Feb 1 '16 at 0:49

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • To make sense of what your code does I think we need to see precisely what TOC you are running the presented code against, and precisely what is output by it. If you have not already done so I think you should look into the properties available on the Layer objects that ListLayers gives you access to. – PolyGeo Jan 30 '16 at 10:06
  • You "have a MXD with one empty group layer inside it", so if that group layer is called "my_group_layer", then your code is returning what I would expect. I think you should now throw your code at some TOCs which are more complicated to demonstrate its shortcomings for what you seem to be saying you are trying to do, but I also recommend that you read and re-read your question to see if you can make what you are asking clearer. – PolyGeo Jan 30 '16 at 10:35
2

I think you just need to read the esri help file on ListLayers so you understand what it is actually being returned.

This is the link. http://desktop.arcgis.com/en/desktop/latest/analyze/arcpy-mapping/listlayers.htm

In particular, note how the layers are listed and how you can use the longName property of the layers to determine which layers belong to a group (or not).

Input from Damijan

I have an empty group layer inside my map and I am looking for a way of initiating a process if there are 0 layers inside the group layer.

It appears you want to know whether a group layer is actually empty or contains layers or sub layers/groups.

Here is the code to accomplish this task:

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

grpListSplit = []
grpListSplit2 = []
grpListSplitFinal = []

for grp in arcpy.mapping.ListLayers(mxd):
    # if longName contains \\ it means that it is inside the group layer
    if '\\' in grp.longName and (grp.isFeatureLayer or grp.isRasterLayer or grp.isNetworkAnalystLayer or grp.isRasterizingLayer or grp.isServiceLayer or grp.isGroupLayer):
        # make sure to obtain the first item, that is group layer name from the longName
        grpListSplit.append(grp.longName.split('\\')[0])
    # if layer does not contain \\ in longName and it is a group layer it means that it is the top group layer - you exclude the sub-group layers
    elif '\\' not in grp.longName and grp.isGroupLayer:
        grpListSplit2.append(grp2.longName)        

Taken from https://stackoverflow.com/questions/35713093/how-can-i-compare-two-lists-in-python-and-return-not-matches and slightly modified

def returnNotMatches(a, b):
    return [x for x in b if x not in a]

grpListSplitFinal = returnNotMatches( grpListSplit,grpListSplit2 )
print grpListSplitFinal

And the result:

[u'Name', u'New Group Layer']

Now do something with the grpListSplitFinal. E.g remove those empty group layers

for grp in arcpy.mapping.ListLayers(mxd):
    if grp.name in grpListSplitFinal:
        if grp.isGroupLayer:     
            arcpy.mapping.RemoveLayer(df, grp)

Both Name and New Group Layers were actually empty group layers.

Some caveats:

  1. If you have more than one Group layer (an empty one and non-empty) with the same name (the main group layer not the sub-group layer) the comparison (returnNotMatches) will not work. This is because group layers name would appear in both lists. E.g. Group Layer has a name Cars and it is empty and we have another group layer with the same name containing layers and/or the sub-groups (with or without layers) then the same group layer name will appear in both lists (grpListSplit and grpListSplit2).

Possible solution:

Use something like

for i in grpListSplit:
    print i + " : " + str(grpListSplit.count(i)) 

and then apply condition based on the count.

  1. If you are removing an empty Layer group and you have sub group layer with the same name under another group layer, this sub group layer will be also removed. E.g. Cars (an empty group layer) and Transport\Cars would be both removed.

Possible solution:

This could be probably solved by using indexes. Look here https://stackoverflow.com/questions/17133028/arcgis-python-index-of-layer-within-a-dataframe for the example.

  1. Also code as it is will work only on the first data frame.

Solution:

Expand code that will loop through data frames

for d in arcpy.mapping.ListDataFrames(mxd):
    print d.name

Even better solution than above is to simply loop through all group layers as such:

mxd = arcpy.mapping.MapDocument("CURRENT")

cnt = 0
df = arcpy.mapping.ListDataFrames(mxd,'')[0]
listLayers = arcpy.mapping.ListLayers(mxd, '', df)
for lyr in listLayers:
   if lyr.isGroupLayer:
      for subGroup in lyr:
         cnt += 1

      if cnt == 0:
         # To rename Group layer
         lyr.name = lyr.name + "_EMPTY"
         # To delete empty Group layer
         arcpy.mapping.RemoveLayer(df, lyr)


  cnt = 0
1

To test whether a layer or group layer returned by arcpy.mapping.ListLayers() is a layer or a group layer you can use the isGroupLayer property of a Layer object:

Returns True if a layer is a group layer.

For example, to progress your code you could try changing:

for lyr in arcpy.mapping.ListLayers(mxd, "my_group_layer", df):
     group.append(lyr)

to:

for lyr in arcpy.mapping.ListLayers(mxd, "my_group_layer", df):
    if lyr.isGroupLayer:
        print lyr.name + " is a group layer"
        group.append(lyr)
    else:
        print lyr.name + " is a normal layer"

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