How can I update multiple feature class attribute tables with the same values?

6554
9
01-05-2015 01:18 PM
AllenSmith
New Contributor

I have a geodatabase with multiple feature classes in multiple feature datasets.  Each feature class has several fields which are identical and will carry the same value.  I want to use python to update all of the fields with the user inputted values.  I can use sys.argv to get the values but how do I pass them to every field in the geodatabase?  I have attached the code I have written so far but nothing gets populated.  Any help would be greatly appreciated.  TIA.

0 Kudos
9 Replies
XanderBakker
Esri Esteemed Contributor

There are easier ways to do this with less code. What version of ArcGIS are you using? If you have 10.1 SP1 or higher you can make use of the data access module. If can you tell me the version I can rewrite the code.

0 Kudos
AllenSmith
New Contributor

Thanks for the help.  I am running 10.1 with SP1.  Any help you could offer would be greatly appreciated.

0 Kudos
XanderBakker
Esri Esteemed Contributor

The code would look something like this. Now be aware that I don't have any data to test the code against. I added an extra parameter where you should provide the path to the workspace (eg file geodatabase). This is required to be able to use the list featureclasses correctly.

I excluded the mxd part in the beginning of the code since it is not used and requires the code to be execute

Please make a copy of your data before you execute the code!

The idea behind the code is that you collect the parameters (although i would probably use the arcpy.GetParameterAsText(#) for this purpose) and then you create a dictionary that related the fieldnames (key) to the value to be stored in that field (value). There is also a check to exclude fields from the list that are not present in the featureclass. Since Python is case sensitive a field that has the same name, but does not match case wise, will not be updated.

import arcpy
import os
import sys

#Set Overwrite Option
arcpy.env.overwriteOutput = True

#Sets parameters (attributes)
AFENumber = sys.argv[1]
RequestID = sys.argv [2]
CreatedDate = sys.argv[3]
CompletionDate = sys. argv [4]
AssetArea = sys.argv[5]
County = sys.argv[6]
State = sys.argv [7]
Country = sys.argv[8]
Datum = sys.argv[9]
CreatedBy = sys.argv[10]
DeliverableStatus = sys.argv[11]
CollectionMethod = sys.argv [12]
GPSType = sys.argv[13]
Geoid = sys.argv[14]

# additional parameter to provide the workspace
ws = sys.argv[15]

# create a dictionary with the field name and corresponding value
dct_fld_val = {'STD_AFE_NUMBER': AFENumber,
               'STD_DATUM_D': Datum,
               'STD_CREATED_DATE': CreatedDate,
               'STD_APC_ASSET_CODE_D': AssetArea,
               'STD_COUNTRY_D': Country,
               'STD_COUNTY_D': County,
               'STD_CREATED_BY_D': CreatedBy,
               'STD_DELIVERABLE_STATUS_D': DeliverableStatus,
               'STD_GPS_TYPE': GPSType,
               'STD_GEOID_D': Geoid,
               'STD_STATE_D': State,
               'STD_SURVEY_COLLECTION_METHOD_D': CollectionMethod,
               'STD_SURV_COMPLT_DATE': CompletionDate,
               'STD_SURVEY_REQ_NUMBER': RequestID}

# fields to update
flds_upd = dct_fld_val.keys()

# you have to set the workspace to be able to use the ListDatasets and ListFeatureClasses
arcpy.env.workspace = ws
fds = arcpy.ListDatasets(feature_type='Feature')
fds.append('') # to include featureclasses that are not within a feature dataset

for fd in fds:
    fcs = arcpy.ListFeatureClasses(feature_dataset=fds)
    for fc in fcs:
        # verify that the fields are actually in the featureclass
        fc_pathname = os.path.join(ws, fd, fc)
        flds_fc = [fld.name for fld in arcpy.ListFields(fc_pathname)]
        flds = list(set(flds_upd) & set(flds_fc))

        # loop through rows of fc
        with arcpy.da.UpdateCursor(fc_pathname, flds) as curs:
            for row in curs:
                for fld in flds:
                    row[flds.index(fld)] = dct_fld_val[fld]
                curs.updateRow(row)

If you run into problems, please post the error you get and if possible a small part of the data, so I can see where the code fails.

AllenSmith
New Contributor

It runs successfully but nothing gets updated. I'll send some sample data in a bit. Thanks for your help with this.

Sent from my iPhone

0 Kudos
AllenSmith
New Contributor

Attached is a sample geodatabase containing one of 40+ feature datasets.  As I mentioned previously, the tool runs successfully (no errors) in 2 seconds but no fields get updated with the user inputted values.  Thanks again.

0 Kudos
XanderBakker
Esri Esteemed Contributor

I did a test with the code below and noticed a small error:

Change the code on line 52 from

fcs = arcpy.ListFeatureClasses(feature_dataset=fds)

to

fcs = arcpy.ListFeatureClasses(feature_dataset=fd)

Since I don't know what you are specifying as parameters I did the test with the adapted code below, which updated the featureclasses in the fgdb:

import arcpy
import os
import sys

#Set Overwrite Option
arcpy.env.overwriteOutput = True

###Sets parameters (attributes)
##AFENumber = sys.argv[1]
##RequestID = sys.argv [2]
##CreatedDate = sys.argv[3]
##CompletionDate = sys. argv [4]
##AssetArea = sys.argv[5]
##County = sys.argv[6]
##State = sys.argv [7]
##Country = sys.argv[8]
##Datum = sys.argv[9]
##CreatedBy = sys.argv[10]
##DeliverableStatus = sys.argv[11]
##CollectionMethod = sys.argv [12]
##GPSType = sys.argv[13]
##Geoid = sys.argv[14]
##
### additional parameter to provide the workspace
##ws = sys.argv[15]

import datetime
date = datetime.datetime.now()

AFENumber = "AFENumber"
RequestID = "ReqID01"
CreatedDate = date
CompletionDate = date
AssetArea = "Asset01"
County = "myCounty"
State = "myState"
Country = "myCountry"
Datum = "01/06/2015"
CreatedBy = "Xander"
DeliverableStatus = "Deliverable"
CollectionMethod = "CollectMethod01"
GPSType = "myGPS"
Geoid = "GeoID01"

# additional parameter to provide the workspace
ws = r"D:\Xander\GeoNet\MultiAttsUpdate\gdb\Sample.gdb"

# create a dictionary with the field name and corresponding value
dct_fld_val = {'STD_AFE_NUMBER': AFENumber,
               'STD_DATUM_D': Datum,
               'STD_CREATED_DATE': CreatedDate,
               'STD_APC_ASSET_CODE_D': AssetArea,
               'STD_COUNTRY_D': Country,
               'STD_COUNTY_D': County,
               'STD_CREATED_BY_D': CreatedBy,
               'STD_DELIVERABLE_STATUS_D': DeliverableStatus,
               'STD_GPS_TYPE': GPSType,
               'STD_GEOID_D': Geoid,
               'STD_STATE_D': State,
               'STD_SURVEY_COLLECTION_METHOD_D': CollectionMethod,
               'STD_SURV_COMPLT_DATE': CompletionDate,
               'STD_SURVEY_REQ_NUMBER': RequestID}

# fields to update
flds_upd = dct_fld_val.keys()

# you have to set the workspace to be able to use the ListDatasets and ListFeatureClasses
arcpy.env.workspace = ws
fds = arcpy.ListDatasets(feature_type='Feature')
fds.append('') # to include featureclasses that are not within a feature dataset
for fd in fds:
    fcs = arcpy.ListFeatureClasses(feature_dataset=fd)
    # fcs = arcpy.ListFeatureClasses(feature_dataset=fds) ######

    for fc in fcs:
        # verify that the fields are actually in the featureclass
        fc_pathname = os.path.join(ws, fd, fc)
        flds_fc = [fld.name for fld in arcpy.ListFields(fc_pathname)]
        flds = list(set(flds_upd) & set(flds_fc))

        # loop through rows of fc
        with arcpy.da.UpdateCursor(fc_pathname, flds) as curs:
            for row in curs:
                for fld in flds:
                    row[flds.index(fld)] = dct_fld_val[fld]
                curs.updateRow(row)

I attach the updated file geodatabase for you to verify. If you don't get it to work, then we have to take a look at the parameters (since there are date field and those may require some extra attention).

0 Kudos
santhoshp
Occasional Contributor

Dear firiends,

I also have same question but i have different fields how i will do that fields plz help me .

I have a geodatabase with multiple feature classes in multiple feature datasets.  Each feature class has same fields which are identical and will carry the same value. plzhelp me.

I have fields in the below.

BUILDING_ID

COMMENT

DISCIPLINE_CODE

DRAWING_REFERENCE

FLOOR_ID

OWNERSHIP_CODE

PARCEL_ID

SUBDISCIPLINE_CODE

Thanks

Snathosh

0 Kudos
XanderBakker
Esri Esteemed Contributor

You would basically have to change the fixed values to assign to the fields and the dictionary that holds the relation between the field names and the fixed values. Something like this:

import arcpy
import os
import sys

#Set Overwrite Option
arcpy.env.overwriteOutput = True

# additional parameter to provide the workspace
ws = r"D:\Xander\GeoNet\MultiAttsUpdate\gdb\Sample.gdb"

# fixed values to assing to fields
building_id = 'your building id'
comment = 'your comment'
discipline_code = 'your discipline code'
drawing_ref = 'your drawing reference'
floor_id = 'your floor id'
ownership_code = 'your ownership code'
parcel_id = 'your parcel id'
subdiscipline_code = 'your subdiscipline code'

# create a dictionary with the field name and corresponding value
dct_fld_val = {'BUILDING_ID': building_id,
               'COMMENT': comment,
               'DISCIPLINE_CODE': discipline_code,
               'DRAWING_REFERENCE': drawing_ref,
               'FLOOR_ID': floor_id,
               'OWNERSHIP_CODE': ownership_code,
               'PARCEL_ID': parcel_id,
               'SUBDISCIPLINE_CODE': subdiscipline_code}

# fields to update
flds_upd = dct_fld_val.keys()

# you have to set the workspace to be able to use the ListDatasets and ListFeatureClasses
arcpy.env.workspace = ws
fds = arcpy.ListDatasets(feature_type='Feature')
fds.append('') # to include featureclasses that are not within a feature dataset
for fd in fds:
    fcs = arcpy.ListFeatureClasses(feature_dataset=fd)
    for fc in fcs:
        # verify that the fields are actually in the featureclass
        fc_pathname = os.path.join(ws, fd, fc)
        flds_fc = [fld.name for fld in arcpy.ListFields(fc_pathname)]
        flds = list(set(flds_upd) & set(flds_fc))

        # loop through rows of fc
        with arcpy.da.UpdateCursor(fc_pathname, flds) as curs:
            for row in curs:
                for fld in flds:
                    row[flds.index(fld)] = dct_fld_val[fld]
                curs.updateRow(row)

Change:

  • the workspace on line 9
  • the fixed values on lines 12 to 19
0 Kudos
santhoshp
Occasional Contributor

Dear Xander Bakker,

Thank you So much it is working.

Thanks

Santhosh

0 Kudos