50

I'm creating a fictive map and so I need to create lots of points, lines and for sure polygons. Later on I export my data as geojson. But before that I aways have to go and give every element an unique ID.

I don't need a special sorting, like the biggest polygon gets the smallest ID or so. I just need all polygons with an ID at the end, without doing it manually like I have to do now.

Would be great if someone knows how to do that.

4
  • Are you using shapefiles? Do the ID's have to be the same after every export, or could you populate the ID field after every edit session? Commented Jan 29, 2015 at 18:27
  • How are you creating the polygons from a script, digitizing in the QGIS desktop, or copying from a shapefile etc.? Commented Jan 29, 2015 at 18:37
  • Well I create a shape in QGIS, Save as Geojson and it's fine. Sorry maybe I got your question in a wrong way?
    – kwoxer
    Commented Jan 29, 2015 at 18:39
  • I would like to add that this doesn't seem to work when you are using a postgreSQL database layers. $ID and $rownum all return 0. PostgreSQL 9.6 QGIS 2.18.12
    – MrKingsley
    Commented Aug 25, 2017 at 13:28

11 Answers 11

58

Using the field calculator is the way to go:

No ID was given in

  1. Digitize every features without any entering any Id.
  2. Before export, update unique Ids with the expression, '$Id' using the field calculator.

No ID given

Some ID's already given in

  1. If you have already ID's you can use '-$Id'. Make sure you just select new Features what means that that are 'NULL' in the id row. Simply do that by ordering the column.
  2. Now do the steps from the pictures:

enter image description here enter image description here

2
  • 1
    Yeah, awsome. Super easy and working properly. Thanks man. Btw: maybe you know how to also do that on already some existing ID's? IF I do this I get -2 -3 and so on
    – kwoxer
    Commented Feb 3, 2015 at 9:57
  • Found a solution and added it to your post. Thanks again.
    – kwoxer
    Commented Feb 3, 2015 at 10:17
30

Hallelujah! Or Eureka. Or whatever. This can be done. With a shapefile.

  1. If there isn't already one, add a field to contain the feature id, say "FID", of type Whole number (integer).
  2. Open Layer Properties (right-click on the layer and choose Properties... or double-click the layer), click on the Attributes Form tab, then under General uncheck Editable and under Defaults in the field Default value type maximum("FID") + 1.

By unchecking Editable, you can't enter another value or delete what's there. Note that if there are values without an ID, these values won't be updated. At some point I'll experiment with checking Apply default value on update and revising my formula to check for a zero or NULL value to update only those records when they are edited, not any record with a value greater than 1. (Earlier in this post it was discussed how to update the FID field with unique values, which you will need to do if you added the field after there were already features in the shapefile.)

Note that this is saved with the current map file, not the shapefile, so adding that shapefile multiple times will require you to copy that part of the layer style to the newly added layer. To do this, right-click on the layer, choose Styles > Copy Style > Fields, and right-click on another layer, choose Styles > Paste Style > All Style Categories (or continue to Fields). You can also copy that part of the style to any other layer based on a shapefile, but the ID field must have the same name as the layer you're copying from.

Layer properties

6
  • 1
    Note that for this to work, you have to at least create one feature and type in its FID then change the attribute form Default value. Otherwise, you end up with a NULL FID.
    – Techie_Gus
    Commented Oct 10, 2019 at 7:06
  • 12
    you can also avoid a NULL FID with the formula: if (maximum("id") is NULL, 1 ,maximum("id") + 1)
    – LeoC
    Commented Mar 10, 2020 at 15:13
  • 5
    to prevent that the "id" of a feature is incremented as soon it get's updated this formula should work as default value (with ticked checkbox "Apply on update"). Reason: Newer QGIS versions (here on 3.14) won't allow that box to be unchecked when using a field in the expression (which is rather strange): IF ("id" is NULL,maximum("id") + 1, "id")
    – sn1ks
    Commented Jun 25, 2020 at 10:31
  • You can also set the widget type to Range and set its minimum value to 1 to avoid using "if" in the expression. This is on 3.16 and didn't need to enable the "Apply on update" option and it still worked.
    – Techie_Gus
    Commented Nov 2, 2020 at 10:06
  • THIS IS THE SOLUTION. I tested it and it is exactly what I was looking for. Many Thanks
    – ClaudeVer
    Commented Mar 3, 2022 at 16:11
14

I would like to add to vinayan's post and briefly mention the rownum function, as it is very similar and in some cases might be a little more convenient.

enter image description here

id returns the Feature ID, meaning that it always starts at zero.
rownum returns the number of the row, meaning that it starts at one.

enter image description here

So, basically, if you want the auto-increment to start at 0 go for $id, and if you want it to start at 1 then go for $rownum.

1
  • Tried out and also a good solution indeed. But with this solution here if you have already some IDs and want to keep them the rownum function is not good. That function always start with 1. The way above is counting way more intelligent even though it's harder to set up. So thanks for the alternative but for now the ID function is my prefered solution =)
    – kwoxer
    Commented Feb 13, 2015 at 8:32
14

Update for QGIS 3

I know I am quite late to this but always good to give any updates:

In QGIS 3 there is now a native tool that can be used to do this exact job and it is called the "Add autoincremental field".

No need to use an expression in the field calculator or do any coding but nevertheless these are all still very useful and good to know.

enter image description here

1
  • 2
    This will create incremented values for existing features but not for new ones. Use bkepl answer to create incremented values for new features. Commented Feb 27, 2020 at 22:02
5

This topic has come up here: Create Shapefile with auto increment primary key in QGIS

My suggestions would be:

1) SQLITE / SpatialLite databases support auto-incrementing on a field set to INTEGER PRIMARY KEY:

On an INSERT, if the ROWID or INTEGER PRIMARY KEY column is not explicitly given a value, then it will be filled automatically with an unused integer, usually the one more than the largest ROWID currently in use. This is true regardless of whether or not the AUTOINCREMENT keyword is used.

Each time you edit/create polygons, you can fill out their attributes, and SQLITE will give it an incremental unique value in the field you have set to INTEGER PRIMARY KEY type.

When you're ready to export to GEOJSON, you're all set with your UNIQUE ID's.

2) If using Shapefiles, create an OBJECTID field of INTEGER type and use a field calculator expression to populate that field each time you edit/create polygons and need to export them. You will lose the original ID a polygon once had, but you this is the only way to achieve this using .SHP. (I will have to find the field calculator expression).

PostGIS is another data source you might want to explore, though more of a heavy lift than SQLITE, you might find value in such a system as you move forward...

2
  • Thanks for explaining. But I don't think it will be any good solution instead of an auto_increment option directly in the tool. I already have so many data formats and don't want yet another tool. Maybe I should write an addon for that when I have some time...
    – kwoxer
    Commented Jan 29, 2015 at 19:57
  • It might be easier to abandon the .SHP! Who knows what new ventures it will take you on... Commented Jan 29, 2015 at 19:59
5

Old post but for anyone else looking for a speedy solution mine was to create a field with $ID + 1 and it will automatically generate starting with 1!

2

If you don't need something humanly digestlible, there is now an easy fix: In the field propreties, select "UUID Generator", and leave everything blank.

This will automatically create a UUID in the field. Not as friendly as a simple number (as per $id or $rownum), but generates the UUID right from the start, so no successive steps.enter image description here

1
  • I'll try to remember the phrase “If you don't need something humanly digestible” for stuff formatted for machines to read. Also, if you are still using the same software, kindly update your answer ;) (maybe I'll do it later myself, but I should be doing something else right now)
    – thymaro
    Commented Dec 23, 2022 at 7:40
0

you can just delete the first colmn (id) and create new one "As virtual field" enter image description here enter image description here

0

Simply copy the files and create a CSV copy and display again creating OIDs and export as new shapefile or feature class.

-1

these solutions no longer worked for me in QGIS 2.01 Dufour. Typing $id on a new or existing field named 'id' in the expression input field gave me an error "Expression is invalid"

What did work was to type the function $rownum and then click "OK"

enter image description here

1
  • As stated earlier - only works on existing layers. Therefore not an answer.
    – CARTOS
    Commented Jul 23, 2020 at 14:06
-3

The easiest way to do this would be probably with a python script or maybe it's possible with the field calculator. Sorry I don't have one for you, maybe someone else will. In the meantime, I'd search for a python script for it. I've seen a lot about this for ArcGIS, but I'm sure there's something out there for QGIS.

2
  • 1
    Well best would be if there is really nothing, a feature request. I don't want a python script additional to QGIS also if it might be a one-click solution. But thank you.
    – kwoxer
    Commented Jan 29, 2015 at 18:38
  • 1
    No, that´s not a user-freindly and easy approach either.
    – CARTOS
    Commented Jul 23, 2020 at 14:07

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.