5

Using the python console, I am trying to copy values from a virtual field into another non-virtual field. Both fields are integer types but I get NULL in the non-virtual field. I followed the answer in this post: Is it possible to programmatically add calculated fields?

The following code works if both fields are non-virtual but doesn't work if copying from a virtual field. Here is the code:

from PyQt4.QtCore import QVariant
from qgis.core import QgsField, QgsExpression, QgsFeature

vl = QgsVectorLayer("C:\Users\Me\Desktop\Test\\Layer.shp", "Layer", "ogr")
vl.startEditing()

idx = vl.fieldNameIndex( 'Field_1' )             # Field_1 is the non-virtual field

e = QgsExpression( ' "Field_2" ' )               # Field_2 is the virtual field
e.prepare( vl.pendingFields() )

for f in vl.getFeatures():
    f[idx] = e.evaluate( f )
    vl.updateFeature( f )

vl.commitChanges()

This works manually through the Field Calculator.

3
+50

Virtual Fields are saved in the project, not in the layer itself. Shapefiles do not know the concept of virtual layers, only QGIS (projects) do.

If you dynamically load a layer like in the sample code you pasted, there is no project involved and hence no virtual field specification loaded.

You can check with the following code that there is no Field_2:

fields = vl.pendingFields()
for i in range(fields.count()):
    fields[i].name()

You can either

  • load a project with a layer that has virtual field definitions attached and work with the layer loaded this way.

or

So the answer is: the code in the sample does not fail to work because of problems with the virtual field - it does not work because there is no virtual field at all.

  • Thanks Matthias, that makes a lot of sense. I was hoping to include the code in a project macro but I'll play around and see if adding a new virtual field, instead of copying values from one, suits my work =) – Joseph Jun 18 '15 at 9:04
  • If you deliver it with a project macro you could define the virtual fields on a layer in that project and then make your python script use the project layer instead of a dynamically loaded one? – Matthias Kuhn Jun 18 '15 at 9:05
  • Huh good shout! I will see if I can achieve that as it sounds like it should do exactly what I'm looking for. Thanks again! – Joseph Jun 18 '15 at 9:10

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.