Select to view content in your preferred language

Append feature class datasets within gdb to a copied template (also a feature class) in a different gdb problem. HELP!

203
5
Jump to solution
2 weeks ago
Fiona_A
Emerging Contributor

UPDATE: Managed to get it working! 😄 

Hello, 
I've got this script tool for ArcPro and I'm trying to add to it so it takes all feature classes within a gdb and appends to a copied template which is located in a different gdb before dissolving. 

I've referred to online resources and updated the script and it does not flag up an error but the output feature class datasets are empty and i don't know what I am doing wrong.

Could anyone help by editing the code below aso it iterates through a gdb and appends each to a template feature class dataset. Currently, it just take a feature class dataset but ideally i want the script to iterate through a gdb of feature class datasets.

I have also provided a copy of the code with what I have tried and is coming back with empty outputs.

I hope I'm making sense

----------------------------------------------

Original script that takes one reference dataset (this works fine)

 

 

import arcpy
from os import path
import uuid

#load in datasets
refdata = arcpy.GetParameterAsText(0) #a feature class reference dataset (want this to instead be a gdb workspace)
blankdata = arcpy.GetParameterAsText(1) #a blank template where the reference data needs to append too.
output = arcpy.GetParameterAsText(2) #output location - a gdb
year = arcpy.GetParameterAsText(3) #used in naming datasets
   
arcpy.env.workspace = output
arcpy.env.overwriteOutput = True

#make into feature layers for use in script
ref = arcpy.management.MakeFeatureLayer(refdata, 'refdatalayer')
blank = arcpy.management.MakeFeatureLayer(blankdata, 'blanklayer')

arcpy.AddMessage("Make copy of blank dataset with new name...")
new_feature_class_name = "NFI" + year + "_NewPlanting_ToBeValidated"
blankcopy = path.join(output, new_feature_class_name)
arcpy.management.CopyFeatures(blank, blankcopy)

arcpy.AddMessage("Append dataset to copied template...")
fieldmappings = arcpy.FieldMappings()

fieldmappings.addTable(blankcopy)
fieldmappings.addTable(ref)

list_of_fields_we_will_map = []
list_of_fields_we_will_map.append(('Grant_year', 'Grant_Year'))
list_of_fields_we_will_map.append(('GS_Reference', 'Grant_Reference'))
list_of_fields_we_will_map.append(('Country', 'Country'))

for field_map in list_of_fields_we_will_map:
    #Find the fields index by name
    field_to_map_index = fieldmappings.findFieldMapIndex(field_map[0])  
    #Grab "A copy" of the current field map object for this particular field
    field_to_map = fieldmappings.getFieldMap(field_to_map_index)
    #Update its data source to add the input from the the append layer
    field_to_map.addInputField(ref, field_map[1])
    #We edited a copy, update our data grid object with it
    fieldmappings.replaceFieldMap(field_to_map_index, field_to_map)

#Create a list of append datasets and run the the tool
inData = [ref]
arcpy.management.Append(inData, blankcopy, "NO_TEST", field_mapping=fieldmappings)

#arcpy.AddMessage("Dissolve...")
new_feature_class_name1 = "NFI" + year + "_NewPlanting_ToBeValidated_D"
arcpy.management.Dissolve(new_feature_class_name, new_feature_class_name1, ["Source", "Category", "IFT_IOA", "Reason_for_change", "AP_year", "Grant_Year", "Origin", "Country", "GS_Reference", "GUID", "Comments", "Validation"], "",
"SINGLE_PART", "DISSOLVE_LINES")

arcpy.AddMessage("populate GUID...")
with arcpy.da.UpdateCursor(new_feature_class_name1, ["GUID"]) as ucur:
    for row in ucur:
        row[0] = '{'+ str(uuid.uuid4()) + '}'
        ucur.updateRow(row)

 

 

--------------------------------------------------------

Edited script where I've changed the refdata parameter to a gdb and I want to iterate through the feature class datasets within and append to the blank template. Currently the output feature classes are empty and the script tool does not return any error messages.

 

 

import arcpy
from os import path
import uuid

#load in datasets
refdata = arcpy.GetParameterAsText(0) #a gdb workspace that contains reference feature class datasets
blankdata = arcpy.GetParameterAsText(1) #a blank template where the reference data needs to append too.
output = arcpy.GetParameterAsText(2) #output location - a gdb
year = arcpy.GetParameterAsText(3) #used in naming datasets
   
arcpy.env.workspace = output
arcpy.env.overwriteOutput = True

#make into feature layers for use in script
arcpy.AddMessage("Make copy of blank dataset with new name...")
new_feature_class_name = "NFI" + year + "_NewPlanting_ToBeValidated"
blank = arcpy.management.MakeFeatureLayer(blankdata, 'blanklayer')
blankcopy = path.join(output, new_feature_class_name)
arcpy.management.CopyFeatures(blank, blankcopy)

arcpy.env.workspace = refdata
# List all feature classes in the geodatabase
feature_classes = arcpy.ListFeatureClasses()

# Iterate through each feature class and append it to the target feature class
for fc in feature_classes:
    ref = arcpy.management.MakeFeatureLayer(fc, 'refdatalayer')
    arcpy.AddMessage("Append dataset to copied template...")
    fieldmappings = arcpy.FieldMappings()
    fieldmappings.addTable(blankcopy)
    fieldmappings.addTable(ref)
    
    list_of_fields_we_will_map = []
    list_of_fields_we_will_map.append(('Grant_year', 'Grant_Year'))
    list_of_fields_we_will_map.append(('GS_Reference', 'Grant_Reference'))
    list_of_fields_we_will_map.append(('Country', 'Country'))
    
    for field_map in list_of_fields_we_will_map:
    #Find the fields index by name
        field_to_map_index = fieldmappings.findFieldMapIndex(field_map[0])  
    #Grab "A copy" of the current field map object for this particular field
        field_to_map = fieldmappings.getFieldMap(field_to_map_index)
    #Update its data source to add the input from the the append layer
        field_to_map.addInputField(ref, field_map[1])
    #We edited a copy, update our data grid object with it
        fieldmappings.replaceFieldMap(field_to_map_index, field_to_map)

#Create a list of append datasets and run the the tool
    inData = [ref]
    arcpy.management.Append(inData, blankcopy, "NO_TEST", field_mapping=fieldmappings)

arcpy.env.workspace = output
arcpy.env.overwriteOutput = True

#arcpy.AddMessage("Dissolve...")
new_feature_class_name1 = "NFI" + year + "_NewPlanting_ToBeValidated_D"
arcpy.management.Dissolve(new_feature_class_name, new_feature_class_name1, ["Source", "Category", "IFT_IOA", "Reason_for_change", "AP_year", "Grant_Year", "Origin", "Country", "GS_Reference", "GUID", "Comments", "Validation"], "",
"SINGLE_PART", "DISSOLVE_LINES")

arcpy.AddMessage("populate GUID...")
with arcpy.da.UpdateCursor(new_feature_class_name1, ["GUID"]) as ucur:
    for row in ucur:
        row[0] = '{'+ str(uuid.uuid4()) + '}'
        ucur.updateRow(row)

 

 

0 Kudos
1 Solution

Accepted Solutions
Fiona_A
Emerging Contributor

Managed to get it to work. Here's the final script 🙂 

import arcpy
from os import path
import uuid

#load in datasets
refdata = arcpy.GetParameterAsText(0) #a gdb workspace that contains reference feature class datasets
blankdata = arcpy.GetParameterAsText(1) #a blank template where the reference data needs to append too.
output = arcpy.GetParameterAsText(2) #output location - a gdb
year = arcpy.GetParameterAsText(3) #used in naming datasets
   
arcpy.env.workspace = output
arcpy.env.overwriteOutput = True

#make into feature layers for use in script
arcpy.AddMessage("Make copy of blank dataset with new name...")
new_feature_class_name = "NFI" + year + "_NewPlanting_ToBeValidated"
blank = arcpy.management.MakeFeatureLayer(blankdata, 'blanklayer')
blankcopy = path.join(output, new_feature_class_name)
arcpy.management.CopyFeatures(blank, blankcopy)

arcpy.env.workspace = refdata
# List all feature classes in the geodatabase
feature_classes = arcpy.ListFeatureClasses()
arcpy.AddMessage(f"Found {len(feature_classes)} feature classes: {feature_classes}")

# Iterate through each feature class and append it to the target feature class
for fc in feature_classes:
    p = path.join(refdata, fc)
    arcpy.AddMessage(f"ref path: {p}")
    ref = arcpy.management.MakeFeatureLayer(p, 'refdatalayer')
    arcpy.AddMessage("Append dataset to copied template...")
    fieldmappings = arcpy.FieldMappings()
    fieldmappings.addTable(blankcopy)
    fieldmappings.addTable(ref)
    
    list_of_fields_we_will_map = []
    list_of_fields_we_will_map.append(('Grant_Year', 'Grant_year'))
    list_of_fields_we_will_map.append(('GS_Reference', 'Grant_Reference'))
    list_of_fields_we_will_map.append(('Country', 'Country'))
    
    for field_map in list_of_fields_we_will_map:
        arcpy.AddMessage(f"Mapping field {field_map[1]} to {field_map[0]}")
    #Find the fields index by name
        field_to_map_index = fieldmappings.findFieldMapIndex(field_map[0])  
    #Grab "A copy" of the current field map object for this particular field
        field_to_map = fieldmappings.getFieldMap(field_to_map_index)
    #Update its data source to add the input from the the append layer
        field_to_map.addInputField(ref, field_map[1])
    #We edited a copy, update our data grid object with it
        fieldmappings.replaceFieldMap(field_to_map_index, field_to_map)

#Create a list of append datasets and run the the tool
    inData = [ref]
    arcpy.management.Append(inData, blankcopy, "NO_TEST", field_mapping=fieldmappings)

arcpy.env.workspace = output
arcpy.env.overwriteOutput = True

#arcpy.AddMessage("Dissolve...")
new_feature_class_name1 = "NFI" + year + "_NewPlanting_ToBeValidated_D"
arcpy.management.Dissolve(new_feature_class_name, new_feature_class_name1, ["Source", "Category", "IFT_IOA", "Reason_for_change", "AP_year", "Grant_Year", "Origin", "Country", "GS_Reference", "GUID", "Comments", "Validation"], "",
"SINGLE_PART", "DISSOLVE_LINES")

arcpy.AddMessage("populate GUID...")
with arcpy.da.UpdateCursor(new_feature_class_name1, ["GUID"]) as ucur:
    for row in ucur:
        row[0] = '{'+ str(uuid.uuid4()) + '}'
        ucur.updateRow(row)

View solution in original post

0 Kudos
5 Replies
DanPatterson
MVP Esteemed Contributor

Code formatting ... the Community Version - Esri Community

so that your code has line numbers to which one can refer.

Also, a couple of print statements at each stage would help to see if anything is actually being done.

For example the section following fc in featureclasses won't actually do anything if the featureclass list is empty.


... sort of retired...
Fiona_A
Emerging Contributor

Hi Dan, 
Thank you for this. I've edited the post so I have the original script tool in the response and am asking for help in editing the script so instead of taking 1 feature class reference dataset (refdata), it instead points to a workspace (a gdb) and iterates through all feature class datasets within and appends them to the blank template.

I h hope this makes sense

0 Kudos
Fiona_A
Emerging Contributor
import arcpy
from os import path
import uuid

#load in datasets
refdata = arcpy.GetParameterAsText(0) #a gdb workspace that contains reference feature class datasets
blankdata = arcpy.GetParameterAsText(1) #a blank template where the reference data needs to append too.
output = arcpy.GetParameterAsText(2) #output location - a gdb
year = arcpy.GetParameterAsText(3) #used in naming datasets
   
arcpy.env.workspace = output
arcpy.env.overwriteOutput = True

#make into feature layers for use in script
arcpy.AddMessage("Make copy of blank dataset with new name...")
new_feature_class_name = "NFI" + year + "_NewPlanting_ToBeValidated"
blank = arcpy.management.MakeFeatureLayer(blankdata, 'blanklayer')
blankcopy = path.join(output, new_feature_class_name)
arcpy.management.CopyFeatures(blank, blankcopy)

arcpy.env.workspace = refdata
# List all feature classes in the geodatabase
feature_classes = arcpy.ListFeatureClasses()

# Iterate through each feature class and append it to the target feature class
for fc in feature_classes:
    ref = arcpy.management.MakeFeatureLayer(fc, 'refdatalayer')
    arcpy.AddMessage("Append dataset to copied template...")
    fieldmappings = arcpy.FieldMappings()
    fieldmappings.addTable(blankcopy)
    fieldmappings.addTable(ref)
    
    list_of_fields_we_will_map = []
    list_of_fields_we_will_map.append(('Grant_year', 'Grant_Year'))
    list_of_fields_we_will_map.append(('GS_Reference', 'Grant_Reference'))
    list_of_fields_we_will_map.append(('Country', 'Country'))
    
    for field_map in list_of_fields_we_will_map:
    #Find the fields index by name
        field_to_map_index = fieldmappings.findFieldMapIndex(field_map[0])  
    #Grab "A copy" of the current field map object for this particular field
        field_to_map = fieldmappings.getFieldMap(field_to_map_index)
    #Update its data source to add the input from the the append layer
        field_to_map.addInputField(ref, field_map[1])
    #We edited a copy, update our data grid object with it
        fieldmappings.replaceFieldMap(field_to_map_index, field_to_map)

#Create a list of append datasets and run the the tool
    inData = [ref]
    arcpy.management.Append(inData, blankcopy, "NO_TEST", field_mapping=fieldmappings)

arcpy.env.workspace = output
arcpy.env.overwriteOutput = True

#arcpy.AddMessage("Dissolve...")
new_feature_class_name1 = "NFI" + year + "_NewPlanting_ToBeValidated_D"
arcpy.management.Dissolve(new_feature_class_name, new_feature_class_name1, ["Source", "Category", "IFT_IOA", "Reason_for_change", "AP_year", "Grant_Year", "Origin", "Country", "GS_Reference", "GUID", "Comments", "Validation"], "",
"SINGLE_PART", "DISSOLVE_LINES")

arcpy.AddMessage("populate GUID...")
with arcpy.da.UpdateCursor(new_feature_class_name1, ["GUID"]) as ucur:
    for row in ucur:
        row[0] = '{'+ str(uuid.uuid4()) + '}'
        ucur.updateRow(row)
0 Kudos
TonyAlmeida
MVP Regular Contributor

I would start by adding some AddMessages to help you figure out where the issue is.  Here are some locations where I would put them.

arcpy.AddMessage(f"Mapping field {field_map[1]} to {field_map[0]}") will help you compare fields from the input feature class to the template feature class

 

 

feature_classes = arcpy.ListFeatureClasses()
arcpy.AddMessage(f"Found {len(feature_classes)} feature classes: {feature_classes}")

blankcopy = path.join(output_gdb, new_feature_class_name)
arcpy.AddMessage(f"Creating a copy of the blank template: {blankcopy}")
arcpy.management.CopyFeatures(blank, blankcopy)
arcpy.AddMessage("Blank template copied successfully.")

for fc in feature_classes:
    arcpy.AddMessage(f"Processing feature class: {fc}...")

with arcpy.da.UpdateCursor(new_feature_class_name1, ["GUID"]) as ucur:
    for row in ucur:
        row[0] = '{'+ str(uuid.uuid4()) + '}'
        ucur.updateRow(row)
    arcpy.AddMessage("GUIDs populated"


for field_map in list_of_fields_we_will_map:
    arcpy.AddMessage(f"Mapping field {field_map[1]} to {field_map[0]}")
    # Find the fields index by name
    field_to_map_index = fieldmappings.findFieldMapIndex(field_map[0])  
    # Grab "A copy" of the current field map object for this particular field
    field_to_map = fieldmappings.getFieldMap(field_to_map_index)
    # Update its data source to add the input from the append layer
    field_to_map.addInputField(ref, field_map[1])
    # We edited a copy, update our data grid object with it
    fieldmappings.replaceFieldMap(field_to_map_index, field_to_map)
arcpy.AddMessage("Fields mapped successfully.")                     

arcpy.AddMessage(f"Appending {fc} to {blankcopy}...")
arcpy.management.Append([ref], blankcopy, "NO_TEST", field_mapping=fieldmappings)
arcpy.AddMessage(f"Appended {fc} successfully.")

arcpy.management.Dissolve(new_feature_class_name, new_feature_class_name1, ["Source", "Category", "IFT_IOA", "Reason_for_change", "AP_year", "Grant_Year", "Origin", "Country", "GS_Reference", "GUID", "Comments", "Validation"], "",
"SINGLE_PART", "DISSOLVE_LINES")
arcpy.AddMessage("Dissolve completed successfully.")

with arcpy.da.UpdateCursor(new_feature_class_name1, ["GUID"]) as ucur:
    for row in ucur:
        row[0] = '{' + str(uuid.uuid4()) + '}'
        ucur.updateRow(row)
arcpy.AddMessage("Populated successfully.")                     

 

 

 

 

Fiona_A
Emerging Contributor

Managed to get it to work. Here's the final script 🙂 

import arcpy
from os import path
import uuid

#load in datasets
refdata = arcpy.GetParameterAsText(0) #a gdb workspace that contains reference feature class datasets
blankdata = arcpy.GetParameterAsText(1) #a blank template where the reference data needs to append too.
output = arcpy.GetParameterAsText(2) #output location - a gdb
year = arcpy.GetParameterAsText(3) #used in naming datasets
   
arcpy.env.workspace = output
arcpy.env.overwriteOutput = True

#make into feature layers for use in script
arcpy.AddMessage("Make copy of blank dataset with new name...")
new_feature_class_name = "NFI" + year + "_NewPlanting_ToBeValidated"
blank = arcpy.management.MakeFeatureLayer(blankdata, 'blanklayer')
blankcopy = path.join(output, new_feature_class_name)
arcpy.management.CopyFeatures(blank, blankcopy)

arcpy.env.workspace = refdata
# List all feature classes in the geodatabase
feature_classes = arcpy.ListFeatureClasses()
arcpy.AddMessage(f"Found {len(feature_classes)} feature classes: {feature_classes}")

# Iterate through each feature class and append it to the target feature class
for fc in feature_classes:
    p = path.join(refdata, fc)
    arcpy.AddMessage(f"ref path: {p}")
    ref = arcpy.management.MakeFeatureLayer(p, 'refdatalayer')
    arcpy.AddMessage("Append dataset to copied template...")
    fieldmappings = arcpy.FieldMappings()
    fieldmappings.addTable(blankcopy)
    fieldmappings.addTable(ref)
    
    list_of_fields_we_will_map = []
    list_of_fields_we_will_map.append(('Grant_Year', 'Grant_year'))
    list_of_fields_we_will_map.append(('GS_Reference', 'Grant_Reference'))
    list_of_fields_we_will_map.append(('Country', 'Country'))
    
    for field_map in list_of_fields_we_will_map:
        arcpy.AddMessage(f"Mapping field {field_map[1]} to {field_map[0]}")
    #Find the fields index by name
        field_to_map_index = fieldmappings.findFieldMapIndex(field_map[0])  
    #Grab "A copy" of the current field map object for this particular field
        field_to_map = fieldmappings.getFieldMap(field_to_map_index)
    #Update its data source to add the input from the the append layer
        field_to_map.addInputField(ref, field_map[1])
    #We edited a copy, update our data grid object with it
        fieldmappings.replaceFieldMap(field_to_map_index, field_to_map)

#Create a list of append datasets and run the the tool
    inData = [ref]
    arcpy.management.Append(inData, blankcopy, "NO_TEST", field_mapping=fieldmappings)

arcpy.env.workspace = output
arcpy.env.overwriteOutput = True

#arcpy.AddMessage("Dissolve...")
new_feature_class_name1 = "NFI" + year + "_NewPlanting_ToBeValidated_D"
arcpy.management.Dissolve(new_feature_class_name, new_feature_class_name1, ["Source", "Category", "IFT_IOA", "Reason_for_change", "AP_year", "Grant_Year", "Origin", "Country", "GS_Reference", "GUID", "Comments", "Validation"], "",
"SINGLE_PART", "DISSOLVE_LINES")

arcpy.AddMessage("populate GUID...")
with arcpy.da.UpdateCursor(new_feature_class_name1, ["GUID"]) as ucur:
    for row in ucur:
        row[0] = '{'+ str(uuid.uuid4()) + '}'
        ucur.updateRow(row)
0 Kudos