8

I'm writing a generic script which involves writing shapefiles to a directory which are then merged together. After writing the files out to the Output folder, I'm trying to get the saga:mergeshapeslayers algorithm to merge all the files in the Output folder. I have used the Model Builder and although it is helpful to an extent, I find that it is used for specific purposes whereas I am attempting to make a script for generic purposes.

Code:

##Test=name
##Select_folder=folder
##Result=output vector

import os
import glob

path_1 = Select_folder
path = path_1
os.chdir(path)

def function():

    output = glob.glob(path_1 + './*.shp')
    x = 0

    while output[x]:
        for fname in glob.glob("*.shp"):
            outputs_1 = processing.runandload("qgis:fieldcalculator", output[x], 'Number', 1, 10, 0, True, 1 , "C:\Users\Me\Desktop\Output\\"  + fname)
            multiple_0 = glob.glob("*.shp")
            x = x + 1

        if x + 1 > len(output):
            processing.runalg("saga:mergeshapeslayers", output[0], ";".join(multiple_0) , Result)
            break
        else:
            continue

if path_1:
    function()
else:
   pass
  • 1
    Sorry, but I don't know what you are trying to do. What is Z?. What does the function(Z) serve if it returns nothing ? What is the difference between glob.glob(Z + './*.shp')and glob.glob("*.shp")? – gene Jun 10 '14 at 18:18
  • Thanks @gene and apologies, edited the code so that it hopefully looks better. To my limited understanding, the difference is that glob.glob(path_1 + './*.shp') defines where the .shp files are; and glob.glob("*.shp") fetches the filenames of the .shp files. Please correct me if I'm mistaken. – Joseph Jun 11 '14 at 11:52
  • To try to be more clear as to what I want: I can write the shapefiles from a given folder into "C:\Users\Me\Desktop\Output\\". I would then like the saga:mergeshapeslayers to merge all files in that Output folder. The code for the merge algorithm is incorrect and would like to know any solutions. – Joseph Jun 11 '14 at 12:00
5

You can simplify your script without using while... and x, x+1: for simple Python list, it would be best to use for or list comprehensions:

##Test=name
##Select_folder=folder
##Result=output vector

import os
import glob
# folder path of Result shapefile
path_res = os.path.dirname(Result)
# go to Select_folder
os.chdir(Select_folder)
# copy the shapefiles (you don't need to load the shapefiles, so use runalg)
for fname in glob.glob("*.shp"):
     outputs_1 = processing.runalg("qgis:fieldcalculator", fname, 'Number', 1, 10, 0, True, 1 , path_res  + "/"+ fname) 

# paths of the shapefiles in the Result folder with list comprehension
output = [path_res + "/"+ shp for shp in glob.glob("*.shp")]
# merge the shapefiles
processing.runalg("saga:mergeshapeslayers", output[0], ";".join(output) , Result)

Some explications:

#  folder path of the Result shapefile # = path_res
print  os.path.dirname("/Users/Shared/test.shp")
/Users/Shared

# list comprehension
print [shp for shp in glob.glob("*.shp")]
['shape1.shp', 'shape2.shp',..., 'shapen.shp']
print [path_res + "/"+ shp for shp in glob.glob("*.shp")]
['/Users/Shared/shape1.shp', '/Users/Shared/shape2.shp', ...,'/Users/Shared/shapen.shp']

or better with os.path.join (universal, Windows, Linux, Mac OS X):

print [os.path.join(path_res, shp) for shp in glob.glob("*.shp")]
print [os.path.join(path_res, shp) for shp in glob.glob("*.shp")][0] # = output[0]
/Users/Shared/shape1.shp
  • Very clear, concise and incredibly helpful. Thank you very much! One question: Isn't line 3 supposed to be ##Result=output vector? – Joseph Jun 12 '14 at 14:17
  • yes and thanks, corrected, but it is your idea (adapted by me) – gene Jun 12 '14 at 14:19
  • Your adaption has definitely taught me, very much appreciated :) – Joseph Jun 12 '14 at 14:45
3

Found the answer thanks to @gene who's comments helped me focus on the right area. Just had to simply to use glob for the saga:mergeshapeslayers function to call:

multiple_0=glob.glob("*.shp")

Added this to the code above which now merges all files in the folder.

  • can you correct the indentation of your script, please. As proposed, it does not work. – gene Jun 11 '14 at 16:24
  • ok but you can simplify your script (see below) – gene Jun 12 '14 at 13:21
  • 1
    Just in case someone runs into the same problem as I did. saga:mergeshapeslayers wasn't found, but saga:mergelayers does the same thing. This was on 2.12.1 (OS X 10.11.3). – cmyk Feb 19 '16 at 8:50
  • @cmyk - Thanks buddy, I didn't mention in the post but it was an old version of QGIS and the Processing plugin (I think v2.2 for both). – Joseph Feb 19 '16 at 9:58

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.