CalculateField based on attribute in another layer

3093
8
Jump to solution
02-23-2016 07:25 AM
ZdeněkSoldán
Occasional Contributor

Hello

I have list of layers from mxd save in a variable lyrs. I want to copy every layer to file gdb so I use for loop.  I need to preserve original OBJECTID in the new layers so I add a new field originOBJID into new layers. Is there any option/expression how to calculate field in new layer based on attribute OBJECTID from original layer (lyr in the for loop)??

mxd=arcpy.mapping.MapDocument("path")

lyrs=arcpy.mapping.ListLayers(mxd)

for lyr in lyrs:

    layr=arcpy.FeatureClassToFeatureClass_conversion(lyr,in_gdb,lyr.name)

    arcpy.AddField_management(layr,"originOBJID","LONG")

    arcpy.CalculateField_management(layr,"originOBJID","???")

Thanks a lot for help!

0 Kudos
1 Solution

Accepted Solutions
XanderBakker
Esri Esteemed Contributor

To explain a bit how you could do this see the code below:

  • On line 8 and 9 you should specify the paths to the existing input and non-existing output featureclasses (see examples on lines 6 and 7
  • The code will generate a dictionary of the unique field INVCIS versus the original OBJECTID. See lines 15 - 17
  • Next the featureclass is converted to the output featureclass on line 21
  • On line 24 the additional field is added
  • Lines 27 - 36 update the output featureclass and write the original OBJECTID to the field called originOBJID

def main():
    import arcpy
    import os

    # paths to input and output featureclasses
    # Database Connections\Desarrollo 10.1.sde\EPMGIS.DEPTO_TRANSPORTE\EPMGIS.DEPTO_Lyr_Via_Vehi
    # D:\Xander\GeoNet\3Dpoints_3Dlines\gdb\test.gdb\polylineZ
    fc_in = r''
    fc_out = r''

    fld_OIDout = 'originOBJID'
    fld_id = 'INVCIS'

    # generate dictionary (LUT)
    fld_OIDin = arcpy.Describe(fc_in).OIDFieldName
    flds = (fld_id, fld_OIDin)
    dct = {r[0]:r[1] for r in arcpy.da.SearchCursor(fc_in, (flds))}

    # transfer the data
    ws, fc_name = os.path.split(fc_out)
    arcpy.FeatureClassToFeatureClass_conversion(fc_in, ws, fc_name)

    # Add the additional field
    arcpy.AddField_management(fc_out, fld_OIDout, "LONG")

    # Update the unformation
    flds = (fld_id, fld_OIDout)
    with arcpy.da.UpdateCursor(fc_out, (flds)) as curs:
        for row in curs:
            uid = row[0]
            if uid in dct:
                row[1] = dct[uid]
            else:
                # this should not happen
                row[1] = -1
            curs.updateRow(row)

if __name__ == '__main__':
    main()

Question: if you have a unique field to start with, why would you want to hold a reference to the original OBJECTID?

View solution in original post

8 Replies
WesMiller
Regular Contributor III

You could always create a field to hold the OBJECTID before you create the new feature classes

ZdeněkSoldán
Occasional Contributor

Unfortunately I can't. Original data are from SDE gdb connected through user without editing rights.

0 Kudos
WesMiller
Regular Contributor III

You could use a Spatial Join—Help | ArcGIS for Desktop to get the oids and calculate them to your new feature class.

0 Kudos
ZdeněkSoldán
Occasional Contributor

Can you be more specific how to use Spatial Join? I tried it but it didn't join OBJECTIDs from original layer.

0 Kudos
ZdeněkSoldán
Occasional Contributor

Ok when I used ONE TO MANY method field join FID appeared in the new layer made by Spatial Join. But it doesn't solve my problem because this field is still in another layer than I need. I need all fields from layer created by layr=arcpy.FeatureClassToFeatureClass_conversion(lyr,in_gdb,lyr.name) plus one new created originOBJID nothing more. And I can't use fieldmappings to remove duplicated fields because they have the same name.

So is there any option how to transfer needed field from another layer into calculate field and fill the field directly in the "layr" layer???

0 Kudos
XanderBakker
Esri Esteemed Contributor

If you have a unique field (other than the original OBJECTID), you can create a dictionary based on that {uniqueID vs originalOBJECTID} and after the export add the original OBJECTID based on the unique ID.

ZdeněkSoldán
Occasional Contributor

Yes I have other unique field. Please would you be so kind and show me in more detail how to do this?

the other unique field is INVCIS

so I will create dictionary first after that export the layer and how then I add the field from dictionary to exportet layer?? By cursor? Can you please show me how to do that??

Thank you very much

0 Kudos
XanderBakker
Esri Esteemed Contributor

To explain a bit how you could do this see the code below:

  • On line 8 and 9 you should specify the paths to the existing input and non-existing output featureclasses (see examples on lines 6 and 7
  • The code will generate a dictionary of the unique field INVCIS versus the original OBJECTID. See lines 15 - 17
  • Next the featureclass is converted to the output featureclass on line 21
  • On line 24 the additional field is added
  • Lines 27 - 36 update the output featureclass and write the original OBJECTID to the field called originOBJID

def main():
    import arcpy
    import os

    # paths to input and output featureclasses
    # Database Connections\Desarrollo 10.1.sde\EPMGIS.DEPTO_TRANSPORTE\EPMGIS.DEPTO_Lyr_Via_Vehi
    # D:\Xander\GeoNet\3Dpoints_3Dlines\gdb\test.gdb\polylineZ
    fc_in = r''
    fc_out = r''

    fld_OIDout = 'originOBJID'
    fld_id = 'INVCIS'

    # generate dictionary (LUT)
    fld_OIDin = arcpy.Describe(fc_in).OIDFieldName
    flds = (fld_id, fld_OIDin)
    dct = {r[0]:r[1] for r in arcpy.da.SearchCursor(fc_in, (flds))}

    # transfer the data
    ws, fc_name = os.path.split(fc_out)
    arcpy.FeatureClassToFeatureClass_conversion(fc_in, ws, fc_name)

    # Add the additional field
    arcpy.AddField_management(fc_out, fld_OIDout, "LONG")

    # Update the unformation
    flds = (fld_id, fld_OIDout)
    with arcpy.da.UpdateCursor(fc_out, (flds)) as curs:
        for row in curs:
            uid = row[0]
            if uid in dct:
                row[1] = dct[uid]
            else:
                # this should not happen
                row[1] = -1
            curs.updateRow(row)

if __name__ == '__main__':
    main()

Question: if you have a unique field to start with, why would you want to hold a reference to the original OBJECTID?