In order to decrease manual data entry, I would like to automate a task to generate numbers for all buildings inside a parcel starting with 1. For example, I have 4000 parcels and each parcel has many buildings. An example of what I would like to achieve is shown in this diagram:

enter image description here


If you're looking for an ArcGIS solution and you have a bldg footprint polygon layer as your pic indicates, then it may be relatively straightforward to:

1- Perform a spatial join, parcels (source) to bldgs (target) so that your bldgs layer will 'inherit' the parcel IDs of your parcel layer.

2- Add a new numeric field for which to calculate the bld nos.

3- Run the following script which opens an update cursor on the output spatial join fc based on a sort of the parcel ID field. The script is untested, errors are not trapped - comments are included in the code, so modification as required should be easy.

import arcpy

# ---set a few variables in-between the 2 symbols: <> 
# (remove the symbols, no spaces or special char between the quotes)

# your workspace:
arcpy.env.workspace = r'< your workspace pathname >'
# your output fc from the spatial join:
fc = '< your spatial join output fc name >'
# your fieldname for parcel ID:
parcelID = '< parcel id fieldname >'
# your new fieldname for housing the newly assigned bldg number:
bldgNO = '< bldg number fieldname >'

# STOP - no more variables to assign

# the following var is for providing the sort string in UpdateCursor
sort = parcelID + " A"
# create the update cursor object
cursor = arcpy.UpdateCursor(fc, '', '', '', sort)

# initialize counter 'i' and current value 'currentVal' for parcel ID
i = 0
currentVal = ''

# process each row represented by 'bldg'
for bldg in cursor:
    # successive parcelID equiv to currentVal, bldg i
    if bldg.getValue(parcelID) == currentVal:
        bldgNumber = i
        # set the bldg val in the table
        bldg.setValue(bldgNO, bldgNumber)
        # update row object
        # increment i
        i += 1
        # re-init i (currentVal is '' for 1st row, otherwise not equiv to parcel ID)
        i = 1
        # set the bldg val to 1 in the table
        bldg.setValue(bldgNO, i)
        # update row object
        # set currentVal to the current parcel ID used for next row val comparison
        currentVal = bldg.getValue(parcelID)
        i += 1

# finally, del objects to remove locks on data
del bldg
del cursor
  • thank you very much @T. Wayne Whitley,i stooped in this line, how can i assign the variables,cursor = arcpy.UpdateCursor(fc, '', '', '', sort). – GIS Man Nov 4 '12 at 23:24
  • GIS Man - I didn't test the code. However, you should not have to assign any variables after the line: # STOP... – T. Wayne Whitley Nov 4 '12 at 23:46
  • GIS Man - Are you saying the code fails or you don't know how to proceed? You should not have to assign any variables after the line: # STOP... The rest of the script should depend on what you've assigned before that, in other words, where you see '# STOP - no more variables to assign' you should have assigned the 4 variables: arcpy.env.workspace, fc, parcelID, and bldgNO. The cursor object only needs fc and sort. The str variable 'sort' is built from your previously defined parcelID. I'll test this script tomorrow if necessary. – T. Wayne Whitley Nov 4 '12 at 23:54
  • thank u @T. Wayne Whitley, here is the steps that i followed to run the script, i opened my ArcMap MXD, then right clicked on Buildings Layer select Join and relates-join,then join parcels Layer based on ObjectID, then i copied your code in new text on my desktop, then make the variables in the code, set my workspace,then the name of spatial join(parcels),name of parcelID field which is parcels_id,then bldgNO is (Building_id), then saved the text as test.py, finally i opened python window from arc map right click then load the script, the result did not appears successfully. – GIS Man Nov 5 '12 at 8:33
  • here is my standard data that i am working with it, if you want to try it.rghost.net/41356982 – GIS Man Nov 5 '12 at 8:37

you can use QGIS for this operation. Given below is simple steps which is easy for any level of users.

  • Open data in QGIS.
  • Right Click on Layer name and choose "Toggle Editing".
  • Right Click again and Open Attribute Table.
  • Open Field Calculator (Ctrl + I).
  • select "create new field" and say a field name.
  • Expand Record and choose rownum (double click). click ok and it will generate numbers for each record in attribute table.

Open Attribute Table to verify your results

See the screenshots below

toggle layer editing

open attribute table

open field calulator

generate si# for every feature

  • 1
    thanks @rashad i think the code for this solution is the best especially in ArcGIS. – GIS Man Nov 4 '12 at 23:31
  • This will not generate numbers for each parcel starting from 1, as the question requires – nadya Nov 5 '12 at 4:18
  • you can have a dummy layer use random point generation for this. That will be easy for getting 4000 features. as stated in the answer generate rownum using Field Calculator. Now goto parcel layer. right click -> properties -> Join tab select the join layer(dummy layer), join field(generate rownum) target field (your parcel_id from parcel layer). Done. BTW, if you want it in code and that too in arcgis. Yes it wont work – rkm Nov 5 '12 at 4:53
  • Don't you need a spatial join to relate the two datasets? In QGis this function is located here: Vector -> Data Management Tools -> Join Attributes by location – djq Nov 5 '12 at 5:41
  • @djq sorry i only used the spatial join. my mistake :( – rkm Nov 5 '12 at 6:08

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