0

Using QGIS 3.8.0. Despite similar questions out there I can't reproject a vector layer to a geopackage while specifying the original table name in a qgis python processing script. FYI all tablenames have underscores, so no spaces or invalid characters.

I see two options:

  1. processing.run('native:reprojectlayer', alg_params....
  2. QgsVectorFileWriter.writeAsVectorFormat(vlayer, geopP,'utf-8', crsObject, "gpkg")

Option 1: the native:reprojectlayer, I can't see how to specify the table name in the alg_params:

alg_params = { 'INPUT': parameters['inputlayer'], 'TARGET_CRS': parameters['selectcoordinatesystem'], 'OUTPUT': outData}

When I specify the tablename for the geopackage in 'outData', like c:/temp/geopackage.gpkg|layername=buildingData it throws an error:

Could not create layer c:/temp/MyExport.gpkg|layername=buildingData.gpkg: Creation of data source failed (OGR error: sqlite3_open(c:/temp/MyExport.gpkg|layername=buildingData.gpkg) failed: unable to open database file)

So it looks like the 'native:reprojectlayer' output is looking for a destination file ending '.gpkg' and has added that on the end of my table name. Does this algorithm support writing specific tablenames?

The only thing that works is only passing in the gpkg without the table and that repojects the dataset but exports the table with the same name as the geopackage file (c:/temp/MyExport.gpkg|layername=MyExport).

Option 2: Trying QgsVectorFileWriter I'm using vector layer objects taken from the selected layer in the QGIS project:

def initAlgorithm(..

self.addParameter(QgsProcessingParameterVectorLayer(self.selectdataV, 'selectdataV', types=[QgsProcessing.TypeVector], defaultValue=None))

def processAlgorithm(...

layerV = self.parameterAsVectorLayer(parameters, self.selectdataV, context)

layname = layerV.name()

When using SaveVectorOptions() I want to specify layername. options = QgsVectorFileWriter.SaveVectorOptions() options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer options.layerName = layname

writer = QgsVectorFileWriter.writeAsVectorFormat(layer=layObj, fileName=geopP, layerOptions=options, fileEncoding='utf-8', destCRS=crsObject, driverName="gpkg")

I get the error: TypeError: QgsVectorFileWriter.writeAsVectorFormat(): arguments did not match any overloaded call: overload 1: argument 'layerOptions' has unexpected type 'SaveVectorOptions' overload 2: 'layerOptions' is not a valid keyword argument

If I take out layerOptions it will just create the same table name as the Geopackage name like in Option 1.

What am I doing wrong? baring in mind I need to specify the new CRS and table name?

1

I just had to do something similar, and your post helped me get there. I have identified over 700 layers within my organizations shared drive that relate to biological resources but those layers are in both SHP and GDB format, they contain 13 different CRSs, and there are a bunch of duplicate names.

My basic solution was to string together a fix geometry function (I needed to do that step in my workflow) to a reproject layer function and then import into a geopackage. Below is the code for the 2 functions I wrote to solve my problem. Please note that I have the CRS hard coded - you can easily make this value a function parameter but I haven't at this point. Hopefully this helps!

'''
This code takes mess of spatial data on bio resources
and reproject them to CRS 3310 and store in GPKG (to retain long column names
from GDB import formats)
'''
##provide path to GPKG, have layers of interest selected in TOC
def fixGeomThenProjV2(gpkg_path):
    #create list of all selected layers in TOC
    sl = iface.layerTreeView().selectedLayers()
    ##create empty list.  This will store converted files names
    ##This will allow for the names to be unique and avoid overwriting 
    ##because of the several dozen "Point_ge" named vectors
    listOfNames = []
    ##start iteration through list
    for lyr in sl:
        #add name to list of names
        listOfNames.append(lyr.name())
        #get count of that name, this will be appended to iterative names later
        lyrCt = listOfNames.count(lyr.name())
        ##next 2 lines fix the geometries of the lyr and declare the fixed layer as a variable
        fixSHP = processing.run("native:fixgeometries", {'INPUT':lyr,'OUTPUT':'memory:'})
        fixSHPvect = fixSHP['OUTPUT']
        ##next 2 lines reproject the fixed geometry to CRS 3310 and declare the output as a vector variable
        projSHP = processing.run("native:reprojectlayer", {'INPUT':fixSHPvect,
        'TARGET_CRS':QgsCoordinateReferenceSystem('EPSG:3310'),'OUTPUT':'memory:'})
        projSHPvect = projSHP['OUTPUT']
        #declare name of vector, add count of name to end so the name will be unique
        projSHPvect.setName(lyr.name()+str(lyrCt))
        ##print name for QC check of output name
        print ("projSHPvect = " + projSHPvect.name())
        ##run append to GPKG function
        test_append2(projSHPvect,gpkg_path)


def test_append2(lyr,gpkg_path):
    ##set save options
    options = QgsVectorFileWriter.SaveVectorOptions()
    options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
    #declare output layername - remove white space with underscores
    options.layerName = ("_".join(lyr.name().split(' '))).lower()
    layerName = ("_".join(lyr.name().split(' '))).lower()    
    _writer = QgsVectorFileWriter.writeAsVectorFormat(lyr,gpkg_path,options)

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.