1

I have a roads shapefile. In its name field, I'll create a new shapefile per attribute. I already got each unique attribute under name. The for-loop that iterates over the unique attributes and selects the features isn't working.

from qgis.core import QgsProject
 
def split_shp():
    # Parameters
    layer_name = 'bicolRoads_primary_secondary'
    field_name = 'name'
    
    layer = QgsProject.instance().mapLayersByName(layer_name)[0] # road shp
    shp_index = layer.fields().indexOf(field_name) # road shp index
    unique_values = layer.uniqueValues(shp_index) # unique attributes under 'name' field

    for i in unique_values: # for-loop that iterates over the unique attributes
        dog = layer.selectByExpression('field_name=i') # selects features matching i/current attribute
        print(dog)

        #shp_writer = QgsVectorFileWriter.writeAsVectorFormat(layer, new_shp, 'utf-8', \
        #driverName='ESRI Shapefile', onlySelected=True)
    
split_shp()

The result is this

enter image description here

  • 4
    You can do it in two lines: res = processing.run("native:splitvectorlayer", {'INPUT':'/path/to/data.shp','FIELD':'unique_field','FILE_TYPE':1,'OUTPUT':'/my/folder/'}), print(res['OUTPUT_LAYERS']) – Germán Carrillo Jul 18 at 3:27
  • @GermánCarrillo, I think this is for QGIS 2. Mine (3.10) says QgsProcessingException: Error: Algorithm native:splitvectorlayer not found. The current documentation doesn't also show what's the keyword nor the log when running the Split Vector Layer tool. – BallpenMan Jul 18 at 13:21
  • @GermánCarrillo, solved it. Instead of "native:splitvectorlayer", I used "qgis:splitvectorlayer" but it saves per shapefile into a geopackage which is why I opted to make my own script instead of using the tool. Thanks anyways! – BallpenMan Jul 18 at 13:31
  • Here's the link to the documentation docs.qgis.org/testing/en/docs/user_manual/processing_algs/qgis/… – BallpenMan Jul 18 at 13:37
  • 2
    Right, the code I put in my comment is for QGIS 3.14, where the algorithm is already in C++ and accepts the output format (1: Shapefile). Good luck! – Germán Carrillo Jul 18 at 13:57
1

Seems like the return value from layer.SelectByExpression is None even if features are selected.

Try building the query like this:

def split_shp():
    # Parameters
    layer_name = 'ak_riks'
    field_name = 'LAN_KOD'
    
    layer = QgsProject.instance().mapLayersByName(layer_name)[0] # road shp
    shp_index = layer.fields().indexOf(field_name) # road shp index
    unique_values = layer.uniqueValues(shp_index) # unique attributes under 'name' field

    for i in unique_values: # for-loop that iterates over the unique attributes
        s = layer.selectByExpression(""""{0}" = '{1}'""".format(field_name, i))
        print(s, layer.selectedFeatureCount())
        ...

enter image description here

But as commented Split vector layer would be easier. But if you want to do it your way Extract by expression might be easier than selecting then exporting.

| improve this answer | |
  • 1
    Thank you for this! .format(field_name, i) is the line I kept searching for. This is really helpful. Thanks again, @BERA. – BallpenMan Jul 18 at 13:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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