1

I have an mxd with 20+ Feature Classes all with varying degrees of 'formatting' (i.e. most are organized in groups, some are filtered with definition queries, and all have their own unique symbologies).

Occasionally these layers must be updated with new data. I have written a script to automate the process of overwriting an outdated FC with new CSV data.

Here's the twist: The code works perfectly fine. A new FC is indeed produced from the information in the new CSV.

Again there are no errors with my code, but just to give you a look at what I'm doing:

arcpy.MakeXYEventLayer_management(Source_CSV, "Lng", "Lat", Temp_Layer, SR, "")
# Following line removes FC from TOC...
arcpy.FeatureClassToFeatureClass_conversion(Temp_Layer, Target_GDB, Target_FC_name, "", Field_Mapping)
# ...so I re-add it here...
addLayer = arcpy.mapping.Layer(Target_file)
arcpy.mapping.AddLayer(df, addLayer)

The problem in terms of my desired workflow is that FeatureClassToFeatureClass removes the target FC from the map document. I want it to remain there, hence the last two lines of code. Of course when my script re-adds the FC it lacks all of its previous formatting (i.e. symbology, grouping, filtering, etc.) that it had before the tool was run.

How can I update a FC within an open mxd via a Python Script tool without having the FC be removed and thus lose all of its formatting?

Perhaps there's a tool that won't remove the target FC? XYTableToPoint sounds like a good candidate, unfortunately it does not exist in my version of Arc (10.2.2).

Perhaps a SearchCursor / UpdateCursor combination will provide the solution I need? Just seems like a lot more code and processing time than with the above script, so wanted to check with online community before starting over.

  • 1
    You can't delete the feature class without the layer dependent on it being removed. This is by design. You can, of course, truncate the table and append to it. – Vince Jun 7 '18 at 0:04
  • 1
    I think you should also be able to switch the data source underneath the layer as long as you don't delete the data while it is still the source for that layer (which triggers layer removal). – PolyGeo Jun 7 '18 at 0:06
  • @Vince OK, so if I understand correctly... FC2FC necessarily deletes the target FC (if it already exists) before converting the new one. So, my hope of being able to 'overwrite' the previously-existing file (like you would in MS Word) is never going to happen with FC2FC...? – Waterman Jun 7 '18 at 0:25
  • If so, then can you expand a bit on your suggestion @PolyGeo? – Waterman Jun 7 '18 at 0:26
  • My script won't mess up any symbology, grouping, etc in my Map Document if I run it OUTSIDE the Map Doc. That's the low-tech solution. Much less than satisfying though. – Waterman Jun 7 '18 at 0:45
2

Quick Answer:

As @Vince suggested, instead of using FeatureClassToFeatureClass_management(), try this:

arcpy.TruncateTable_management(Target_FC)
arcpy.Append_management(Temp_Layer, Target_FC, "NO_TEST", Field_Mapping)

...assuming Target_FC = os.path.join(Target_GDB, Target_FC_name)

This way the feature class never gets deleted. It just has its content deleted and replaced.

Note that if Target_FC is versioned, you need to use DeleteRows_management instead of TruncateTable_management, but truncating is quicker than deleting and is the better option for non-versioned datasets.

Extended capabilities and reusability:

If your temp_layer has the exact same schema as your target FC, you can simplify the append to:

arcpy.Append_management(Temp_Layer, Target_FC, "TEST")

Or if the temp_layer has a different schema but all the mapped fields have the same field names in the input and the target, it can automatically map the fields for you:

arcpy.Append_management(Temp_Layer, Target_FC, "NO_TEST")

I often use the following pattern in several scripts. This will create the target FC if it does not already exist, by doing FeatureClassToFeatureClass, and if it does already exist, it will do a truncate/append. For the append, it will firstly attempt with "TEST" and if that fails, it will then use "NO_TEST", simply so that in the output I can get a warning if the schemas do not match (depending on the situation, this can be a useful reminder that the schema in either the source or destination has been changed, and the other may need to be modified to match, otherwise fields will be missed in the automatic field mapping)...

if arcpy.Exists(Target_FC):
    arcpy.TruncateTable_management(Target_FC)
    try:
        arcpy.Append_management(Temp_Layer, Target_FC, "TEST")
    except:
        arcpy.Append_management(Temp_Layer, Target_FC, "NO_TEST")
        print "WARNING:  Source and destination schemas do not match!"
else:
    arcpy.FeatureClassToFeatureClass_conversion(Temp_Layer, Target_GDB, Target_FC_Name)

(In practice, I also check if the input is a feature class (or layer) or a table (or view), and will use either FeatureClassToFeatureClass or TableToTable respectively. Truncate and Append both work fine for either case.)

In fact, I have used this same pattern in so many scripts that I really should put it in a function in a module. Not all of the functionality is required in every situation, but it's a neat way to cover all bases that should work anywhere.

This is UNTESTED, but such a function would look something like:

def replaceDatasetInPlace(source, dest, mapping=None):
    if arcpy.Exists(dest):
        destWorkspace, destName = os.path.split(dest)
        # TruncateTable will not work for a versioned dataset, so fall back to the much slower DeleteRows if necessary
        if arcpy.Describe(dest).isVersioned:
            arcpy.DeleteRows_management(dest)
        else:
            arcpy.TruncateTable_management(dest)
        if mapping:
            arcpy.Append_management(source, dest, "NO_TEST", mapping)
        else:
            try:
                arcpy.Append_management(source, dest, "TEST")
            except:
                arcpy.Append_management(source, dest, "NO_TEST")
                print "WARNING:  Source and destination schemas do not match!"
    else:
        if arcpy.Describe(source).datasetType == 'FeatureClass':
            arcpy.FeatureClassToFeatureClass_conversion(source, destWorkspace, destName, mapping)
        else:
            arcpy.TableToTable_conversion(source, destWorkspace, destName, mapping)
  • Thanks! 'TruncateTable' followed by 'Append' is the solution I was looking for. The detailed explanation, and tip re: versioned / unversioned Feature Classes was much appreciated... and your "Untested" script works like a charm. – Waterman Jun 7 '18 at 21:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.