2

I found a couple of good answers like here for example, but I do not manage to adapt them and make them work...

What i am trying to do: take the input, create new output with same fields, add a new field with values calculated from another field. For the moment, I managed to get the new values for the new field in a list:

from collections import Counter as counter

layer = qgis.utils.iface.activeLayer()
features = layer.getFeatures()

# find the index of the 'relict_id' field.
idx = layer.fieldNameIndex('RELICT_ID')

relict_id = []
for feat in features:
    attrs = feat.attributes()
    relict_id.append(attrs[idx])

relict_id_new = [x for x in relict_id]

c = counter(relict_id)
idx = 0
while idx in range(len(relict_id)):
    rel_id = relict_id[idx]  
    if c[rel_id] != 1:
        for x in range(c[rel_id]):
            relict_id_new[idx+x] = '{}_{}'.format(relict_id[idx],x)
        idx += c[rel_id]
    else:
        idx +=1

I would like now to adapt this answer, but all I get is a bunch of errors. I tried to get rid off Processings since it does not seem to work for me (QGIS 2.18.2). I am not understanding pretty well the implication of the processes, I do not know if it is the good way to do it and what are the problems.

Here is the code for creating the new shapefile and new field:

##testes=group
##Ratio =name
##layer=vector
##output_file=output vector

from PyQt4.QtCore import QVariant, QFileInfo
from qgis.core import QGis, QgsFeature, QgsField, QgsFields, QgsProject
import processing

layer= iface.activeLayer().dataProvider().dataSourceUri()
layer = path[:path.rfind('|')]

mylayer = QgsVectorLayer(layer, "inventaris_points_in_roi_single_new", "ogr")
if not mylayer.isValid():
    print("Layer failed to load!")

vectorLayer = processing.getObject(mylayer)
provider = vectorLayer.dataProvider()

New_layer= processing.getObject(layer)
fields = QgsFields()
fields = provider.fields()
fields.append(QgsField('AREA', QVariant.Double,'',20,3))
fields.append(QgsField('PERIMETER', QVariant.Double,'',20,3))
fields.append(QgsField('RATIO', QVariant.Double,'',20,3))

writer = processing.VectorWriter(output_file, None, fields.toList(),
                              QGis.WKBMultiPolygon, New_layer.crs())

features = processing.features(vectorLayer)
for feat in features:
    writer.addFeature(feat)

del writer

And the error :

Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "c:/users/hocquetfp/appdata/local/temp/tmp_oajpe.py", line 18, in <module>
    vectorLayer = processing.getObject(mylayer)
  File "C:/Program Files/QGIS 2.18/apps/qgis/./python/plugins\processing\tools\dataobjects.py", line 216, in getObject
    ret = getObjectFromUri(uriorname)
  File "C:/Program Files/QGIS 2.18/apps/qgis/./python/plugins\processing\tools\dataobjects.py", line 244, in getObjectFromUri
    if normalizeLayerSource(layer.source()) == normalizeLayerSource(uri):
  File "C:/Program Files/QGIS 2.18/apps/qgis/./python/plugins\processing\tools\dataobjects.py", line 222, in normalizeLayerSource
    source = source.replace('\\', '/')
AttributeError: 'QgsVectorLayer' object has no attribute 'replace'
2
  • I think the problem is making the layer object. Your currently using two methods (iface.activeLayer() AND QgsVectorLayer(). Where is the location of the vector layer your wanting to add fields to (loading in QGIS or not in QGIS)?
    – artwork21
    Commented Jun 22, 2018 at 12:26
  • Thanks for the answer. The vector layer is loaded in QGIS and I use the python console/editor. But I am using the QGIS 2.18.2 version, and I read this w-e that there are some issues using that method and QGIS version before 2.18.9 ... as I am not the administrator, i need to wait for the it guy to download an actual version and verify. I will also add the first part of the question that i manage.
    – francois
    Commented Jun 25, 2018 at 6:16

1 Answer 1

1

In QGIS select the active layer (you want to copy fields from) and use this code snippet in the python console:

layer= iface.activeLayer()
tempLayer = QgsVectorLayer("Polygon", "temporary_poly", "memory")
temp_data = tempLayer.dataProvider()
attr = layer.dataProvider().fields().toList()
temp_data.addAttributes(attr)
temp_data.dataProvider().addAttributes([QgsField('AREA', QVariant.Double,'',20,3)])
temp_data.dataProvider().addAttributes([QgsField('PERIMETER', QVariant.Double,'',20,3)])
temp_data.dataProvider().addAttributes([QgsField('RATIO', QVariant.Double,'',20,3)])
tempLayer.updateFields()
QgsMapLayerRegistry.instance().addMapLayer(tempLayer)

This code snippet will take the selected active layer copy its fields into a new empty memory layer, add additional fields, and load it into QGIS. This layer is only a memory layer at this point. You could use the QgsVectorFileWriter.writeAsVectorFormat() method to save the layer to disk as a shapefile or other ogr formats.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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