3

I have al lot of shapefiles who share zero, one, some or all fields. I want to write an expression that can be used on all of the shapefiles.

I was wondering if there is something like if "field1" exists do ... else nothing?

In fact I want to create a virtual field that - let's say - sum every field.

  • Not in the classic field calculator as far as i know as it won´t work with non existing columns, even in the CASE statement. With python it should be easy. – Matte Sep 7 '16 at 12:18
  • @Matte: Can you give me an example of python code that will do that? Can you add a virtual field with python that will work with nonexisting fields? – PieterB Sep 7 '16 at 12:31
  • As the answer from Matthias Kuhn does work nicely you can use this approach without python and just with the CASE eval('"field"') and the combinations what need to be done when you have one or more fields. – Matte Sep 7 '16 at 13:04
  • 1
    @Germán Carillo I just made a request. I'm looking forward to it :-) – PieterB Sep 7 '16 at 13:56
  • 1
    I've implemented your suggestion, it's included in v0.4.0 of AutoFields. Please let me know if it helps you solve the question. While QGIS people approves the new version, you can get it from here. – Germán Carrillo Sep 9 '16 at 17:23
5

I don't think there is a possibility to check if a certain field exists. However, if a field doesn't exist, the its value will be reported as NULL.

Now there is one remaining problem, that the prepare() which QGIS performs will check if all your fields are there (which is normally a desired behavior).

You can workaround this for certain parts of your code by wrapping them in an eval statement. Please note that this exploits undocumented behavior and may change anytime in the future!

The following expression will return TRUE if the field does not exist

eval('"field1"') IS NULL

Often you don't even have to check because

eval('"field1"') * 3

will itself return either NULL or 3 times the value of field1 because the nature of NULL values is that they get propagated.

If you want to replace a non-existent value with some other value you can use the COALESCE function.

Basic usage, replace field1 with 0 when unavailable

COALESCE( eval("field1"), 0 )

And a more complex example of how to put this together in an expression

COALESCE( eval("scale_factor"), 1 ) * ( COALESCE( eval("field1"), 0 ) + "field_which_is_always_available" )

This will replace scale_factor with 1 if unavailable, field1 with 0 if unavailable and the last one will always have to be there or your whole expression will result in an empty (NULL) value.

Please note: If you have NULL values inside your data, the result will obviously be the same as if the field does not exist. This may be in line with your requirements but it's something to keep in mind.

  • I tried both to add a field and virtual field based on the sum of an existing and non existing field and I get an evaluation error that says Colomn 'nonexisting' not found – PieterB Sep 7 '16 at 12:24
  • Damned, it only works in the preview and fails on the "prepare()" step when executing for real. Update coming. – Matthias Kuhn Sep 7 '16 at 12:31
  • I'm struggling with that. Let's say I just want to sum each field. How is the right syntax? – PieterB Sep 7 '16 at 13:40
  • 1
    I just figured it out with if (eval('"field1"') is null, 0, "field1") + if (eval('"field2"') is null, 0, "field2") + if (eval('"field3"') is null, 0, "field3"). But with coalesce it looks more elegant. Thanks! – PieterB Sep 8 '16 at 7:32
2

You can evaluate if a field exist this way too within field calculator:

from qgis.core import *
from qgis.gui import *
import qgis

def fieldExist(fieldName):
    lyr = qgis.utils.iface.activeLayer()
    fieldIndex = lyr.fieldNameIndex(fieldName)
    return fieldIndex

@qgsfunction(args='auto', group='Custom')
def myFunction(value1, feature, parent):
    index = fieldExist('fieldNameHere')
    if index >-1:
        # field exists do something else
  • 1
    Very good approach! You could propse that to expressionsplus plugin to make deployment easier. – Matthias Kuhn Sep 7 '16 at 13:28
  • I'm not familiar with python. Maybe I have to dive in it once – PieterB Sep 7 '16 at 14:28
  • index = getActiveLayer('fieldNameHere') should be index = fieldExist('fieldNameHere') in myFunction? – Kadir Şahbaz May 15 '18 at 12:15
  • @Kadir, updated thx! – artwork21 May 15 '18 at 12:17

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.