0

I have a folder of shapefiles which I want to append to project geodatabase feature classes using ArcPy. So far, as I am testing with just a few shapefiles, the script works fine as long as all the fields match and there is no field mapping involved. However, I would like to include field mapping with the code, but being relatively new to Python and ArcPy, I am having trouble understanding the best way to do this.

I would like to match the following fields: "reference" (in shapefile) with "ID" (feature class in GDB) and "riskcategory" (in shapefile) with "risk" (feature class in GDB).

My current code is below:

import arcpy
import os

#Set up workspace
workspace_in = arcpy.GetParameterAsText(0)
workspace_out = arcpy.GetParameterAsText(1)
arcpy.env.workspace = workspace_in

#Set target datasets
targetPt = os.path.join(workspace_out, "tree_location_pt")
targetPly = os.path.join(workspace_out, "tree_location_ply")

#get a list of shapefiles
survey = arcpy.ListFeatureClasses()

#loop shapefiles in folder
for fc in survey:
    if fc == "export_Point.shp":
        arcpy.management.Append(fc, targetPt, "NO_TEST")
    elif fc == "export_Polygon.shp":
        arcpy.management.Append(fc, targetPly, "NO_TEST")

3
  • 2
    Please Edit the Question to include one or more of the field_mapping parameters you have attempted and include any error(s).
    – Vince
    Nov 2, 2023 at 19:00
  • I would like to rephrase - the code that I have now works without field mapping, how can I add a field map for the two fields described in the main question? Any parameters that I might have tried are examples of other people's codes or ESRI append tool examples online and having tested them without actually understanding what I was doing. Now I finally have a code that works without field mapping - I would like to know what I can add to the current code to make a field map work? Thank you.
    – user-0326
    Nov 2, 2023 at 19:32
  • Your code looks like ArcGIS for Desktop, in that case you can create a field map object resources.arcgis.com/en/help/main/10.2/index.html#//… if you know the from and to field names... beware of types though, mapping a text to date (for example) is likely to result in facepalms. You can get info on input fields using ListFields(YourFC,FieldName)[0].type ListFields resources.arcgis.com/en/help/main/10.2/index.html#//… field type resources.arcgis.com/en/help/main/10.2/index.html#//… Nov 3, 2023 at 0:57

4 Answers 4

1

I have struggled with the fieldmap object myself, but figured it out eventually. Here's how it works. This should work in both ArcGIS Desktop and ArcGIS Pro.

source = r"path-to-source-featureclass"
target = r"path-to-target-featureclass"

# Get field objects from target featureclass
fields = arcpy.ListFields(target)

# Create a new object that will hold the field mappings
mappings = arcpy.FieldMappings()

# repeat the following 4 lines for every field you want to map
fieldmap = arcpy.FieldMap()
fieldmap.addInputField(source, "field-in-source")
fieldmap.outputField = next(f for f in fields if f.name == "field-in-target")
mappings.addFieldMap(fieldmap)

arcpy.management.Append(source, target, 'NO_TEST', mappings)

Note that inputField can be specified as just the fieldname (a string value), but outputField must be a field object.

3
  • I have tested this code exactly as you have specified with my own source/target names. The script runs with no errors, but field mapping does not get read. The data transfers with empty attributes. I have managed to create a field mapping object successfully according to Append Example 3 [pro.arcgis.com/en/pro-app/latest/tool-reference/data-management/… but, can only make it work for one target (I have two targets, polygon and point feature classes) - the target I place first in the script gets read. Have not found a way to include field map objects for multiple targets.
    – user-0326
    Nov 3, 2023 at 10:22
  • You will probably need to generate separate mapping for each target, because the outputFields are specific to the target of the Append method
    – Berend
    Nov 3, 2023 at 11:12
  • Another option is to run the tool from a toolbox first, and generate Python code from the tool's result window. That might give you some idea for your own script
    – Berend
    Nov 3, 2023 at 11:15
0
import arcpy
import os

#Set up workspace
workspace_in = arcpy.GetParameterAsText(0)
workspace_out = arcpy.GetParameterAsText(1)
arcpy.env.workspace = workspace_in

#Set target datasets
targetPt = os.path.join(workspace_out, "tree_location_pt")
targetPly = os.path.join(workspace_out, "tree_location_ply")

#get a list of shapefiles
survey = arcpy.ListFeatureClasses()

#loop shapefiles in folder
for fc in survey:
    if fc == "export_Point.shp":
        # arcpy.management.AddField(fc, "reference", "LONG",)  # 1. shp add field.
        # arcpy.management.AddField(fc, "riskcategory", "TEXT",field_length=50) 
        ## Field are added automatically when calulating field
        arcpy.management.CalculateField(fc, "reference", "!ID!")  # 2. calulate field.
        arcpy.management.CalculateField(fc, "riskcategory", "!risk!") 
        arcpy.management.Append(fc, targetPt, "NO_TEST")  # 3. append shp to fc.
    elif fc == "export_Polygon.shp":
        # Same as pt
        arcpy.management.Append(fc, targetPly, "NO_TEST")
0

I have managed to find a solution to this now so wanted to share my solution in case anyone ever comes across a similar issue. Maybe this is not the most elegant solution and can be trimmed down but it works - something that I was never able to achieve with ModelBuilder due to differing geometry types.

I have created the field mapping objects and append tool for point and polygon classes inside functions to be able to set separate field mapping targets due to differing geometries - and then calling these functions in the end of the script.

import arcpy
import os


def append_pt(workspace_in, workspace_out):

    #Set up workspace
    workspace_in = arcpy.GetParameterAsText(0)
    workspace_out = arcpy.GetParameterAsText(1) 
    arcpy.env.workspace = workspace_in


    #Set target datasets
    targetPt = os.path.join(workspace_out, "tree_location_pt")

    #Set local variables
    schemaType = "NO_TEST"
    fieldMappings = ""
    subtype = ""

    #Get a list of shapefiles
    surveypt = arcpy.ListFeatureClasses()

    #Create FieldMappings object
    fieldMappings = arcpy.FieldMappings()

    # Add the target table to the point field mappings class to set the schema
    fieldMappings.addTable(targetPt)

    #Add input fields for  point "reference"
    fldMap = arcpy.FieldMap()
    fldMap.addInputField("export_Point.shp", "reference")

    #Set the name of new output field
    ID = fldMap.outputField
    ID.name = "ID"
    fldMap.outputField = ID

    #Add output field to field mapping object
    fieldMappings.addFieldMap(fldMap)

    #Add input fields for "riskcatego"
    fldMap = arcpy.FieldMap()
    fldMap.addInputField("export_Point.shp", "riskcatego")

    #Set the name of new output field
    risk = fldMap.outputField
    risk.name = "Risk"
    fldMap.outputField = risk

    #Add output field to field mapping object
    fieldMappings.addFieldMap(fldMap)

    #loop shapefiles in folder
    for fc in surveypt:
        arcpy.AddMessage(fc)
        if fc == "export_Point.shp":
            arcpy.management.Append(fc, targetPt , schemaType, fieldMappings, subtype)

#Repeat the function above but for polygon dataset parameters

#Call append function
append_pt("arcpy.GetParameterAsText(0)", "arcpy.GetParameterAsText(1)")
append_ply("arcpy.GetParameterAsText(0)", "arcpy.GetParameterAsText(1)")
arcpy.AddMessage("Append Complete")

-1

Maybe you should use the Add Relate (Data Management)https://pro.arcgis.com/en/pro-app/latest/tool-reference/data-management/add-relate.htm?

Make Feature Layer (Data Management) https://pro.arcgis.com/en/pro-app/latest/tool-reference/data-management/make-feature-layer.htm

arcpy.management.MakeFeatureLayer(shp, shp_layer)     
arcpy.management.AddRelate(shp_layer, "reference", fc, "ID", "Relate_A") # Relate_A in workspace, fc in gdb or shp in floder. 
arcpy.management.AddRelate(shp_layer, "riskcategory", fc, "risk", "Relate_B")

arcpy.management.MakeFeatureLayer("realPath_Relate_A", Relate_A_layer) 
arcpy.management.AddRelate(Relate_A_layer, "FID_SHP", "Relate_B", "FID_SHP", "RESULT")
1
  • 1
    The Append is used for the purpose of uploading survey data collected in the field weekly into a project database, so would really need to go with that particular tool. I would have the option to just change my geodatabase fields to match the survey fields or vice versa, but would very much like to figure out the field_mappings (since I know it is possible) without having to change existing practices.
    – user-0326
    Nov 2, 2023 at 20:11

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.