Merge Shapefiles with Attributes Using PyQGIS – How to

mergepyqgisshapefile

I have some shapefiles. They are all the same kind of shape and all have the same attributes.

If I wanted to merge them manually the "Vector/Data management tools/merge shapefiles to one" works fine.

However, as per the question title, I'd like to do this using Python from a script.

I went hunting for the "merge shape files" in the hopes I could cobble it into my script but I couldn't find it.

I tried writing one myself iterating over the features and copying them into another layer as per the pyQGIS cookbook but lost the attributes along the way.

feature_list = inputlayer.getFeatures()
  for feature in feature_list:
    (res, outFeats) = outputlayer.dataProvider().addFeatures( [ feature ] )

I also tried writing a script using the iface copy features function with the same loss of attributes as a result.

qgis.utils.iface.setActiveLayer(importlayer)
importlayer.setSelectedFeatures(range(100))
#(there are exactly 100 features)
qgis.utils.iface.actionCopyFeatures().trigger()
iface.setActiveLayer( outputlayer )
outputlayer.startEditing()
qgis.utils.iface.actionPasteFeatures().trigger()

Can someone help me fix my code to retain the copied attributes or point me to a pyQGIS script to achieve this result?

Best Answer

OK here's the answer. I have discovered the processing toolbox from which there was a simple solution: As per http://qgis.org/de/docs/user_manual/processing/console.html

From the console you can get a list of all the algorithms available which contain the word "merge" by typing:

import processing
processing.alglist("merge")

Then you could find out how to use the most appropriate function with:

processing.alghelp("qgis:mergevectorlayers")

Then simply use the algorithm in your script as follows:

processing.runalg("qgis:mergevectorlayers", layer1, layer2,"outputfilename.shp")

On the other hand manually merging shapes may still be useful. For those who still want to manually copy features from an input layer into some destination layer with attributes you need to first make sure the destination layer has those fields.

old_attribute_List = input_layer.dataProvider().fields().toList()
new_attribute_List=[]
for attrib in old_attribute_List:
  if destination_layer.fieldNameIndex(attrib.name())==-1:
    new_attribute_List.append(QgsField(attrib.name(),attrib.type()))
destination_layer_data_provider.addAttributes(new_attribute_List)
destination_layer.updateFields()

Then to manually copy over the features you can do:

destination_layer.startEditing()
cfeature = QgsFeature()
cfeatures=[]
xfeatures = input_layer.getFeatures()
for xfeature in xfeatures:
    xgeometry = xfeature.geometry()
    #GEOMETRY TRANSFORM GOES HERE IF DESTINATION CRS DIFFERS FROM INPUT CRS
    cfeature_Attributes=[]
    cfeature_Attributes.extend(xfeature.attributes())
    cfeature.setGeometry(xgeometry)
    cfeature.setAttributes(cfeature_Attributes)
    cfeatures.append(cfeature)
destination_layer_data_provider.addFeatures(cfeatures)
destination_layer_data_provider.commitChanges()
Related Question