8

I'm working with QGIS 3.10 A Coruña on MacOS 10.13 environment. I have a vector polygon layer and I need to select features with a given attribute value and export them as a new shapefile. I'm a newbie in these matters and haven't get any further than

layer = qgis.utils.iface.mapCanvas().currentLayer()
request = QgsFeatureRequest(QgsExpression("CODNUT2 = 'ES24'"))
features = layer.getFeatures(request)
  1. What should be the next steps to generate the shapefile with those selected features?
  2. How to make it an iterative process to generate new shapefiles for every value in the CODNUT2 attribute?
1
  • You can use code in my answer for obtaining a memory layer with your request.
    – xunilk
    Commented Jan 24, 2021 at 17:44

4 Answers 4

8

You can use the following script. Just change folder.

layer = qgis.utils.iface.mapCanvas().currentLayer()

field_name = "CODNUT2"
idx = layer.fields().indexOf(field_name)
unique_values = layer.uniqueValues(idx)

folder = "/path/to/folder"

for value in unique_values:
    file_path = f"{folder}/_{value}.shp"
    layer.selectByExpression(f"{field_name}='{value}'")
    
    QgsVectorFileWriter.writeAsVectorFormat(layer,
                                            file_path,
                                            'utf-8',
                                            layer.crs(),
                                            "ESRI Shapefile",
                                            onlySelected=True
                                            )
7

I would use two processing tools to achieve your problem: qgis:listuniquevalues to get the unique values and native:saveselectedfeatures to save the selected feature.

layer = iface.activeLayer()

# Find the unique values for the given field
res1 = processing.run("qgis:listuniquevalues",
                      {'INPUT': layer,
                       'FIELDS': ['CODNUT2'],
                       'OUTPUT': 'TEMPORARY_OUTPUT',
                       'OUTPUT_HTML_FILE': 'TEMPORARY_OUTPUT'})
distinct_value = res1['OUTPUT']

# Loop trough the unique values
for feat in distinct_value.getFeatures():
    attr_value = feat['CODNUT2']  # distinct value 

    # Select the objects with the unique value
    layer.selectByExpression(f"CODNUT2='{attr_value}'")

    # Exported selected objects to shp
    processing.run("native:saveselectedfeatures",
                   {'INPUT': layer,
                    'OUTPUT': f'C:/Users/ncipa/Downloads/test_selectedtest_{attr_value}.shp'})
3
  • It certainly creates all expected files, but they are all empty. No features have been included in any of them.
    – jpinilla
    Commented Jan 24, 2021 at 17:31
  • Yes, it is the field name of my test data.
    – Nil
    Commented Jan 24, 2021 at 17:43
  • Please refer to up to date documentation)
    – Taras
    Commented Jan 24, 2021 at 18:25
6

There is a better approach for what you want to do with processing and the native splitvectorlayer algorithm.

Just do :

import processing
params = {'INPUT':iface.activeLayer(),
'FIELD':'CODNUT2',
'FILE_TYPE':0,
'OUTPUT':'/path/to/folder'}
processing.run("native:splitvectorlayer", params)

Put 'FILE_TYPE':1 if you want shpfile

To get the help :

processing.algorithmHelp('native:splitvectorlayer') #in the console
1
  • This is the recommended answer! Commented Jul 15, 2021 at 0:58
4

You can use following code for obtaining a memory layer with your request:

qgis.utils.iface.mapCanvas().currentLayer()

request = QgsFeatureRequest().setFilterExpression (u"CODNUT2 = 'ES24'")

selected_feats = layer.getFeatures(request)

attr = [ feat.attributes() for feat in selected_feats ]
idx = [ ele[0] for ele in attr ]
val_req = [ ele[1] for ele in attr ]

iterator = layer.getFeatures(request)

feats = [ feat for feat in iterator ]

epsg = layer.crs().postgisSrid()

uri = "Polygon?crs=epsg:" + str(epsg) + "&field=id:integer""&field=CODNUT2:string""&index=yes"

mem_layer = QgsVectorLayer(uri, 
                           'mem_layer', 
                           'memory')

prov = mem_layer.dataProvider()

for i, feat in enumerate(feats):
    feat.setAttributes([idx[i], val_req[i]])
    mem_layer.addFeature(feat)

prov.addFeatures(feats)

QgsProject.instance().addMapLayer(mem_layer)

For testing it, I created 'CODNUT2' field in one shapefile and arbitrarily put in it some 'ES24' values and other different.

After running above code, result was as expected. Memory layer has features with desired request and corresponding ids.

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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