2

I'm currently using QGIS 3.30 and I'm trying to set a default value for a field based on multiple other fields, without having the default value update automatically whenever an attribute of the feature is updated. The expression I'm using is as follows:

CASE
  WHEN count("AID") = 0 THEN
    regexp_replace(
      upper(
        concat(
          coalesce(left(rpad("vorname", 1, 'X'), 3), 'X'),
          coalesce(left(rpad("name", 1, 'X'), 3), 'X'),
          coalesce(left(rpad("rolle", 1, 'X'), 3), 'X'),

          lpad('1', 4, '0'),
          @nis_project_id
        )
      ),
      '[^a-zA-Z0-9]',
      '_'
    )
  ELSE
    regexp_replace(
      upper(
        concat(
          coalesce(left(rpad("vorname", 1, 'X'), 3), 'X'),
          coalesce(left(rpad("name", 1, 'X'), 3), 'X'),
          coalesce(left(rpad("rolle", 1, 'X'), 3), 'X'),
          lpad(
            to_string(
              maximum(to_int(substr("AID", 4, 4))) + 1
            ),
            4,
            '0'
          ),
          @nis_project_id
        )
      ),
      '[^a-zA-Z0-9]',
      '_'
    )
END

The goal is to generate an ID based on the values of other fields when a new feature is created, but not to have the ID change if the feature is updated.

When I set the 'Apply default value on update' option, the ID is generated as expected, but also updates every time an attribute of the feature changes, which is not what I want.

When I do not set the 'Apply default value on update' option, the ID is not generated correctly when I input a new feature. It seems to ignore the values of other fields that are supposed to be used in generating the ID.

Could anyone guide me on how to set the default value based on the expression above, such that it considers the values of other fields at the time of feature creation and does not update automatically with each feature update?

Edit: Even with unchecked "edidable" it's still updating: enter image description here

New Edit: I want the AID to be updated while the user is typing:

enter image description here

Here is a siplyfied test-project: Test-Project

3
  • 1
    Wait... why do you even need to have 'Apply default value on update' checked if you only want the ID to be generated on feature create? The default expression should still work as long as you are creating a new feature. When I have generated auto incrementing ID fields I always have 'Apply default value on update' unchecked....
    – she_weeds
    Commented Jun 19, 2023 at 0:21
  • The answer is: I would like the generated ID to be displayed while the user is filling out the form.
    – MartinMap
    Commented Jun 22, 2023 at 6:19
  • I added a new screen record to my question...
    – MartinMap
    Commented Jun 22, 2023 at 6:27

3 Answers 3

5
+100

You could check if the id-variable is negative (at feature creation) and modify your expression so it calculates the value for the column AID only as long as @id is negative:

( 'Apply default value on update' option activated )

 CASE WHEN @id <0 THEN
 
    CASE
      WHEN count("AID") = 0 THEN
        regexp_replace(
          upper(
            concat(
              coalesce(left(rpad("vorname", 1, 'X'), 3), 'X'),
              coalesce(left(rpad("name", 1, 'X'), 3), 'X'),
              coalesce(left(rpad("rolle", 1, 'X'), 3), 'X'),

              lpad('1', 4, '0'),
              @nis_project_id
            )
          ),
          '[^a-zA-Z0-9]',
          '_'
        )
      ELSE
        regexp_replace(
          upper(
            concat(
              coalesce(left(rpad("vorname", 1, 'X'), 3), 'X'),
              coalesce(left(rpad("name", 1, 'X'), 3), 'X'),
              coalesce(left(rpad("rolle", 1, 'X'), 3), 'X'),
              lpad(
                to_string(
                  maximum(to_int(substr("AID", 4, 4))) + 1
                ),
                4,
                '0'
              ),
              @nis_project_id
            )
          ),
          '[^a-zA-Z0-9]',
          '_'
        )
    END

ELSE "AID"

END
6
  • Sorry, but this is not working. I don't know why, but after changing the expression, the AID isn't built up anymore from "name", "vorname", and "roll". Only the number updates.
    – MartinMap
    Commented Jun 21, 2023 at 17:01
  • @MartinMap: Do you have a test-dataset? Is "@nis_project_id" a project variable ?
    – Thomas B
    Commented Jun 22, 2023 at 7:10
  • 1
    Can you try it with CASE WHEN @id <0 THEN (see answer updated )
    – Thomas B
    Commented Jun 22, 2023 at 8:16
  • 1
    YES! that's it!
    – MartinMap
    Commented Jun 22, 2023 at 8:18
  • 1
    Fantastic answer, I think I might try this out for QField as well.
    – she_weeds
    Commented Jun 22, 2023 at 11:34
1

As you remarked correctly, the default-value checkbox needs to be checked, otherwise feature generation doesn't work.

If you uncheck the editable checkbox at the top of your attributes form, the ID wont change when you edit the feature.

enter image description here

4
  • Sounds simple and nice, but it doesn't work. Also, when "editable" is unchecked, the field is still updating.
    – MartinMap
    Commented Jun 14, 2023 at 8:14
  • Seems like "update" means "updating the attribute table", but not "moving the feature". I only checked the latter.
    – Erik
    Commented Jun 14, 2023 at 8:59
  • 2
    just one idea for a workaround: does it work if you a: check apply default value on update b: first check if the AID column is still empty and only then apply your logic? CASE WHEN AIS IS NULL THEN ... your expression ... END I guess in this case the desired behaviour for the initial filling of the coulumn would work and would not be changed by other attribute updates... for sure just a workaround but perhaps it helps
    – Thomas B
    Commented Jun 15, 2023 at 12:58
  • 1
    @ThomasB feel free to add this as an answer, since it seems to solve the issue.
    – Erik
    Commented Jun 16, 2023 at 8:16
1

Try a python function that returns a value indicating whether the record is being created or updated - something like this:

from qgis.core import *

@qgsfunction(args='auto', group='Custom')
def get_record_status(feature, parent):
    if feature.id() < 0:
       return 'Created'
    else:
       return 'Updated'

Edit the expression for the the ID default value so that it calls this function and generates the ID field if the returned value is 'Created' using the case statement you have already written. If the returned value is 'Updated' do nothing.

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.