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.
You can achieve it by running the following code snippet in the QGIS Python console:
from PyQt4.QtCore import QVariant
for layer in QgsMapLayerRegistry.instance().mapLayers().values():
prefix = layer.name().split("_")[0]
res = layer.dataProvider().addAttributes([QgsField("density", QVariant.String)])
layer.updateFields()
fieldIndex = layer.dataProvider().fieldNameIndex( "density" )
attrFeatMap = {}
attrMap = { fieldIndex : prefix }
for feature in layer.getFeatures():
attrFeatMap[ feature.id() ] = attrMap
layer.dataProvider().changeAttributeValues( attrFeatMap )
I assume the only layers you have loaded in the QGIS ToC are those you want to modify. Otherwise, you would need to validate things like the layer type (i.e., you don't want the script to run on raster layers).
The script iterates through layers loaded into QGIS, extracts the prefix from their names, creates the text field density
, builds a dictionary like this:
{ featureId : { fieldIndex : value } }
for each feature, and finally, applies the dictionary to change features' density values.
Let me know if something is not clear.
Best Answer
dump()
method of QgsLayerTreeLayer should be only used for debug purpose. You can do it much nicer this way:The code above will remove all layers that are immediately inside the group. If the group has subgroups inside and they also have layers, they won't be removed.
If you want to remove the whole group instead (with layers and groups inside), just call: