4

I have a situation as you see below:

enter image description here

I have imported the .dxf file from AutoCAD, which finally looks like the above. Each layer includes lines and polylines. I need to have them merged with each other.

I found some similar problems here:

Batch process for merging features in multiple layers

Merging multiple temporal inputs in QGIS Graphical Modeler

which utilizes the graphical modeler. It does make sense, although I haven't used the graphical modeler so far, therefore I don't know how to start.

Is there a chance to make this merge in one go?

Geographos
  • 4,087
  • 2
  • 27
  • 88

1 Answers1

6

If you are open to a PyQGIS solution, it can be done very simply:

p = QgsProject.instance()

get all layers in project

lyrs = p.mapLayers().values()

filter layers if necessary (could also filter by geometry type)

line_layers = [x for x in lyrs if 'line' in x.name().lower()]

merge layers (don't forget to specify your coordinate system)

merged = processing.run("native:mergevectorlayers", {'LAYERS':line_layers,'CRS':QgsCoordinateReferenceSystem('EPSG:4326'),'OUTPUT':'TEMPORARY_OUTPUT'})['OUTPUT']

add to canvas

p.addMapLayer(merged)

To merge layers per group (using the hierarchy in your screenshot):

# reference to the project
p = QgsProject.instance()

reference to the layer tree

root = p.layerTreeRoot()

reference to the group called 'Batch'

group = root.findGroup('Batch')

loop through all the items in the Batch group

for child in group.children(): # find sub-groups if isinstance(child, QgsLayerTreeGroup):
sub_group = child

    # empty list to store the layers ready to merge
    lyrs_to_merge = []

    # find line layers in the sub-group
    for sub_child in sub_group.children():
        # check whether the child is a layer and has 'line' in its name
        if isinstance(sub_child, QgsLayerTreeLayer) and 'line' in sub_child.name().lower():
            lyr = sub_child
            # add to list
            lyrs_to_merge.append(lyr.layerId())

    # perform merge
    merged = processing.run("native:mergevectorlayers", {'LAYERS':lyrs_to_merge,'CRS':QgsCoordinateReferenceSystem('EPSG:4326'),'OUTPUT':'TEMPORARY_OUTPUT'})['OUTPUT']    

    # name the merged layer
    merged.setName('merged | ' + sub_group.name())

    # add layer to project, but prevent adding to canvas and layer tree (with False) 
    p.addMapLayer(merged, False)

    # insert the merged layer at the top of each sub-group
    sub_group.insertLayer(0, merged)

Result:

enter image description here

Matt
  • 16,843
  • 3
  • 21
  • 52
  • It works, but I need to have it merge not as a whole, but within the given group. How could I change the code? – Geographos Nov 07 '22 at 09:25
  • see my updated answer – Matt Nov 07 '22 at 13:07
  • I see no reaction. Shall I select some particular layer for it? – Geographos Nov 07 '22 at 14:08
  • I have added a screenshot of the resulting layer tree. Each sub-group has a merged layer inserted at the top. – Matt Nov 07 '22 at 14:15
  • I see nothing executed in my QGIS, although he code looks fine. Your answer has been accepted anyway. I will figure out the error from my side. Thank you! – Geographos Nov 07 '22 at 16:28
  • What I wondered was whether the "polylines" layers are MultiLineString and the others LineString. In which case, perhaps the merge is failing. You might need to add a 'multipart to singlepart' step before the merge – Matt Nov 07 '22 at 17:34
  • It might have a sense. Is there any programmatic way to do it? – Geographos Nov 07 '22 at 17:42
  • I just tested and it appears to work with a mixture of Lines and MultiLines, so I don't think that's the issue. Other than making sure the names and group/sub-group levels match your screenshot, I really don't know why you're experiencing problems, unfortunately. – Matt Nov 07 '22 at 18:00
  • I think I must fix my end this time. Thank you very much for your help :) – Geographos Nov 07 '22 at 20:49