Can I change Annotation Expression using Arcpy?

1745
4
12-04-2017 09:31 AM
AllysonReynolds2
New Contributor II

I know how to change an annotation expression using the Properties window for the annotation feature class. But I am trying to automate some schema changes for a client and would like to be able to change the annotation expression just using arcpy. How can I do this?

0 Kudos
4 Replies
XanderBakker
Esri Esteemed Contributor

Yes you can using the LabelClass—Help | ArcGIS Desktop (obtained from the Layer—Help | ArcGIS Desktop ). This class holds the expression. 

AllysonReynolds2
New Contributor II

Xander,

According to the documentation from that Layer page you linked: 

"Not all layers support the labelClasses property (for example, raster layers and annotation layers), so it is good practice to test for this ahead of time using the supports method."

Previous testing has shown that the annotation expression cannot be changed from the layer properties - I need to access the schema properties, not the map/layer settings. So I don't think Layer access helps me.

Thanks for the input though!

0 Kudos
XanderBakker
Esri Esteemed Contributor

Good catch!

I was just looking at a feature-linked annotation and the annotation layer does not contain any access to the expression. It does contain a field TextString that holds the result of the expression. I thought I could update that with a new content (no change in the expression) like this:

def main():
    import arcpy

    # featureclass and relevant fields
    fc = r'C:\Esri\EAB\NFA\Nighttime Flow Analysis\NighttimeFlowA4W\Maps and GDBs\WaterDistributionNetwork.gdb\WaterDistribution\wMain'
    fld_facility = 'FACILITYID'
    fld_mat = 'MATERIAL'
    fld_diam = 'DIAMETER'
    fld_oid = 'OID@'

    # annotation fc and fields
    fc_anno = r'C:\Esri\EAB\NFA\Nighttime Flow Analysis\NighttimeFlowA4W\Maps and GDBs\WaterDistributionNetwork.gdb\WaterDistribution\Water_MainsAnno4'
    fld_anno_id = 'FeatureID'
    fld_text ='TextString'

    # create a dictionary of oid vs relavent attributes
    flds = (fld_oid, fld_facility, fld_mat, fld_diam)
    dct_fc = {r[0]: [r[1], r[2], r[3]] for r in arcpy.da.SearchCursor(fc, flds)}

    # update values
    flds_anno = (fld_anno_id, fld_text)
    with arcpy.da.UpdateCursor(fc_anno, flds_anno) as curs:
        for row in curs:
            feat_id = row[0]
            if feat_id in dct_fc:
                # construct the new "expression"
                lst_values = dct_fc[feat_id]
                text = '{0}\n{1} - {2}'.format(lst_values[0], lst_values[1], lst_values[2])
                curs.updateRow((feat_id, text, ))


if __name__ == '__main__':
    main()

The TextString field values do update with the new text, however that new text is not visualized as annotation in the map. 

Just wondering. Why does this client want to update the annotation by Python? And is there a reason for not wanting to use labeling instead of annotation?

0 Kudos
AllysonReynolds2
New Contributor II

Sorry for the delayed response.

We are scripting a lot of schema changes because they want to be the ones running the changes on the Production environment. (And the changes need to be easily repeatable so they can be applied to Dev, Stage, Prod.)

Yes, with utility maps there are so many features in small areas that annotations are necessary so that they can be moved manually to ensure good visibility of all features. It's also just what they have, so they are maintaining that. 

It looks like we are just going to have to include some manual steps along with the scripted ones. 

0 Kudos