Copy certain tabel fields and exclude field

1714
10
Jump to solution
06-21-2021 11:42 AM
2Quiker
Occasional Contributor II

I am trying to use InsertCurosr to transfer rows from one table to another. Yes I could just use append but I am trying to see if the InsertCurosr is faster but I am getting the error

"DescribeData: Method Field1AFieldName does not exist".

Here is what I have currently. The Source Label currently does not have Field1A, Target does have the Field1A field.

import arcpy,os
#### Transfer Source table rows into Target Table

arcpy.env.workspace = r'C:\Temp\Test.gdb'

Target = r"C:\Temp\Test.gdb\TargetTable"
Source = r"C:\Temp\Test.gdb\SourceTable"
arcpy.DeleteRows_management(Target)

dsc = arcpy.Describe(Target)
fields = dsc.fields
out_fields = [dsc.OIDFieldName, dsc.Field1AFieldName]
fieldnames = [field.name for field in fields if field.name not in out_fields]

with arcpy.da.SearchCursor(Source,fieldnames) as sCur:
   with arcpy.da.InsertCursor(Target,fieldnames) as iCur:
      for row in sCur:
          iCur.insertRow(row)

 

0 Kudos
1 Solution

Accepted Solutions
BlakeTerhune
MVP Regular Contributor

The ObjectID_1 field most commonly happens when you import a feature class that already has an ObjectID field into a geodatabase, which tries to create its own OID field but since the default name is already taken, it names it with _1.

Because of the mismatched field names, you would need to create a field mappings object, which is a bit annoying for just one off-named field. You could recreate the feature class with only the one default named OID field so Append would work without field mappings, or use the cursors as you were attempting to do.

Here's what I would do for cursors

 

dsc = arcpy.Describe(Source)
target_field_Names = [f.name for f in arcpy.ListFields(Source)]
source_field_Names = [
    f.name for f in arcpy.ListFields(Source)
    if f.type != "OID"
    and f.name in target_field_Names
]
with arcpy.da.SearchCursor(Source,fieldnames) as sCur:
   with arcpy.da.InsertCursor(Target,lstFields) as iCur:
      for row in sCur:
          iCur.insertRow(row)

 

And here's what I would do for using append with field mappings. I created a fuzzy_fieldmap() function that will create field mappings only with fields that exist in both the source and target tables (excluding ObjectID fields).

 

import arcpy

def main():
    fieldmappings = fuzzy_fieldmap(sourceTable, targetTable)

    arcpy.Append_management(
        sourceTable,
        targetTable,
        "NO_TEST",
        fieldmappings
    )
    print(arcpy.GetMessages())


def fuzzy_fieldmap(input_table, target_table):
    input_fields = [
        f.name.upper() for f in arcpy.ListFields(input_table)
        if f.type != "OID" or f.name != "OBJECTID"
    ]

    target_fields = [
        f.name.upper() for f in arcpy.ListFields(target_table)
        if f.type != "OID" or f.name != "OBJECTID"
    ]
    # Main FieldMapings object to hold FieldMap objects
    fms = arcpy.FieldMappings()
    # dictionary for FieldMap objects
    fm_vars = {}

    for t_field in target_fields:
        if t_field in input_fields:
            # Create the FieldMap object
            fm_vars[t_field] = arcpy.FieldMap()
            # Add fields to FieldMap object
            # Add target field first so the output gets those field properties
            fm_vars[t_field].addInputField(target_table, t_field)
            fm_vars[t_field].addInputField(input_table, t_field)
            # Add the FieldMap objects to the FieldMappings object
            fms.addFieldMap(fm_vars[t_field])

    # Optional debugging section to print field mappings
    for out_field in fms.fields:
        print("{} ({}): {}".format(out_field.name, out_field.aliasName, out_field.type))

    return fms


if __name__ == '__main__':
    main()

 

View solution in original post

10 Replies
DavidPike
MVP Frequent Contributor

The issue (I guess) is that you're trying to access a property of the describe table object that just doesn't exist.

dsc.Field1AFieldName

Table properties—ArcGIS Pro | Documentation

0 Kudos
2Quiker
Occasional Contributor II

The field Field1A doesn't exist in the source table only in the target. I guess I was thinking that line 12& 13 would take care of that issue for both the Source SearchCuror and the Target InsertCursor.

0 Kudos
DavidPike
MVP Frequent Contributor

you've created a describe object of the Target table then are trying to access a property of that describe object dsc.Field1AFieldName which doesn't exist and is causing the error.  Line 12 imho is the issue.

0 Kudos
BlakeTerhune
MVP Regular Contributor

I concur with @DavidPike . You're trying to reference fields as if there were a join, but there isn't one.

Add Join (Data Management)—ArcGIS Pro | Documentation

0 Kudos
2Quiker
Occasional Contributor II

So can Field1A be skipped/not included when you pass the InsertCurosr, if so how?

0 Kudos
BlakeTerhune
MVP Regular Contributor

@2Quiker wrote:

So can Field1A be skipped/not included when you pass the InsertCurosr, if so how?


 Sure, just leave that field out of the field_names parameter when you open the cursor. You only need to pass back values for the fields that you opened the cursor with.

0 Kudos
2Quiker
Occasional Contributor II

I guess I was completely over thinking it.

dsc = arcpy.Describe(Source)
fields = dsc.fields
#out_fields = [dsc.OIDFieldName]
fieldnames = [field.name for field in fields]

lstFields = [field.name for field in fields]

with arcpy.da.SearchCursor(Source,fieldnames) as sCur:
   with arcpy.da.InsertCursor(Target,lstFields) as iCur:
      for row in sCur:
          iCur.insertRow(row)

 

0 Kudos
BlakeTerhune
MVP Regular Contributor

There's still some redundancy in your code. You can build a list of field names easily this way:

fieldnames = [f.name for f in arcpy.ListFields(Source)]

 But this is getting all the field names. If you want to exclude something, you could do something like:

ignore_fields = ["Field1A", "SomethingElse"]
fieldnames = [f.name for f in arcpy.ListFields(Source) if f.name not in ignore_fields]


As a final note, it looks like you're just straight copying data; might I recommend Append()?

2Quiker
Occasional Contributor II

Thank you for the replies, after looking at the data a little I was wrong, I was working with the wrong data sorry about that.

So the Source table has OBJECTID_1(not sure way but this is how I get the data) and the target has OBJECTID. So the InsurtCur 'Cannot find field 'OBJECTID_1'. The Source OBJECTID_1 should go into the targets OBJECTID but as I said it can't find it. Maybe I am still over thinking it...

If I use append  would the ObjectID vs ObjectID_1 be an issue?

I was trying use understand  search and insert cursors to understand them better.

0 Kudos