Hello,
I'm trying to figure out how to use an updatecursor to update an annotation feature class (specifically moving the annotation, not updating the actual text). There's little documentation on this, but from what I can find I think both the shape field and the element fields need to be updated? I'm trying to use an update cursor with hard-coded values first just to see if the annotation updates (it's a single feature), then change it to be more dynamic later on.
I'm also testing with edit sessions to see if that does anything but nothing seems to update. I don't get any errors either, but it seems like the update cursor is not changing anything. Any ideas?
UPDATE: It's definitely an issue with the blob field. Geometry field is updating fine (tested on another polygon layer), but converting the element field to bytes, making changes, and converting back to blob is something I haven't seen any documentation on. Does anyone know the proper encoding? I'm using UTF-8 by default but playing around with different options.
This is my code so far:
import arcpy, os, json
aprx = arcpy.mp.ArcGISProject(r"C:\MyProject\MyProject.aprx")
for m in aprx.listMaps():
print("Map: {0} Layers".format(m.name))
for lyr in m.listLayers():
if lyr.name == 'testAnno':
cursor = arcpy.da.SearchCursor(lyr, ['SHAPE@','Element'])
for row in cursor:
#print(row[1].tobytes())
print(row[1].tobytes())
print(row[0])
s = row
#view the
print(s[0].JSON)
print(s[1].tobytes())
#hard coded data:
origjson = """{"rings":[[[-75.764363411999966,45.158486504000052],[-73.469080190999989,45.158486504000052],[-73.469080190999989,42.846093335000035],[-75.764363411999966,42.846093335000035],[-75.764363411999966,45.158486504000052]],[[-61.499009848999947,43.715848636000032],[-63.210088402999986,42.185967841000036],[-64.347457697999971,43.458046171000035],[-73.427031740999951,38.791915476000042],[-73.428038225999956,38.791551154000047],[-73.431213794999962,38.792105457000048],[-73.433067308999966,38.794742874000065],[-73.432513005999965,38.797918442000025],[-73.430882073999953,38.799407634000033],[-64.353259686999934,43.46453534300008],[-64.751373533999981,43.909801450000032],[-63.040294979999942,45.439682245000029],[-61.499009848999947,43.715848636000032]]],"spatialReference":{"wkid":4326,"latestWkid":4326}}"""
newjson = """{"rings":[[[-90.580491480999967,44.665072753000061],[-90.580491480999967,42.460838942000066],[-90.579865532999975,42.461430743000051],[-90.577483941999958,42.461614847000078],[-73.428077403999964,38.799780517000045],[-73.427236678999975,38.799506056000041],[-73.425022048999949,38.797163643000033],[-73.425112405999982,38.793941327000027],[-73.427454818999934,38.791726697000058],[-73.42983640999995,38.791542593000031],[-90.57924294899999,42.453376923000064],[-90.58008367299999,42.453651384000068],[-90.580491480999967,42.454082722000066],[-90.580491480999967,42.352679584000043],[-92.875774701999944,42.352679584000043],[-92.875774701999944,44.665072753000061],[-90.580491480999967,44.665072753000061]]],"spatialReference":{"wkid":4326,"latestWkid":4326}}"""
newbytes = """b'\n\x011 \x02*M-92.890214218719606,42.748368221326849;-90.578362387719665,42.7483682213268492\x04test8\x00A\x00\x00\x00\x00\x00\x00\x00\x00z2{"x":-73.4289569073265227,"y":38.7956615549338792}\x81\x01iR\xb2{\xdd\xe5d@\xca\x01\x99\x02{"type":"CIMSimpleLineCallout","lineSymbol":{"type":"CIMLineSymbol","symbolLayers":[{"type":"CIMSolidStroke","enable":true,"capStyle":"Round","joinStyle":"Round","lineStyle3D":"Strip","miterLimit":10,"width":1,"color":{"type":"CIMRGBColor","values":[0,0,0,100]}}]},"autoSnap":true}'"""
origbytes = """b'\n\x011 \x02*M-63.778802929164698,43.241781972225155;-61.466951098164685,43.2417819722251692\x04test8\x00A\x00\x00\x00\x00\x00\x00\x00\x00z2{"x":-73.4289569073265227,"y":38.7956615549338792}\x81\x01iR\xb2{\xdd\xe5d@\xca\x01\x99\x02{"type":"CIMSimpleLineCallout","lineSymbol":{"type":"CIMLineSymbol","symbolLayers":[{"type":"CIMSolidStroke","enable":true,"capStyle":"Round","joinStyle":"Round","lineStyle3D":"Strip","miterLimit":10,"width":1,"color":{"type":"CIMRGBColor","values":[0,0,0,100]}}]},"autoSnap":true}'"""
d = json.loads(s[0].JSON)#getting first record, assuming only 1 anno here for testing
workspace = os.path.dirname(r"C:\Users\dcolombini\Documents\ArcGIS\Projects\MyProject\MyProject.aprx")
# Start an edit session. Must provide the workspace.
edit = arcpy.da.Editor(workspace)
# Edit session is started without an undo/redo stack for versioned data
# Set multiuser_mode to False if working with unversioned enterprise gdb data
edit.startEditing(with_undo=False, multiuser_mode=False)
# Start an edit operation
edit.startOperation()
print('\n UPDATING ANNO \n')
ESBlob = bytearray(origbytes, 'utf-8')
dj = json.dumps(origjson)
# Create update cursor for feature class
for lyr in m.listLayers():
if lyr.name == 'testanno':
for m in aprx.listMaps():
print("Map: {0} Layers".format(m.name))
for lyr in m.listLayers():
if lyr.name == 'testAnno':
print('updating anno layer')
with arcpy.da.UpdateCursor(lyr, ['SHAPE@JSON','Element'], "", sr) as cursor:
for row in cursor:
#print(row)
row[0] = dj #features[0].projectAs('4326')
row[1] = ESBlob
cursor.updateRow(row)
print('\n UPDATE COMPLETE \n')
#del aprx
# Stop the edit operation.
edit.stopOperation()
# Stop the edit session and save the changes
edit.stopEditing(save_changes=True)
print('\n Checking new values \n')
for m in aprx.listMaps():
print("Map: {0} Layers".format(m.name))
for lyr in m.listLayers():
if lyr.name == 'testAnno':
cursor = arcpy.da.SearchCursor(lyr, ['SHAPE@JSON','Element'])
for row in cursor:
print(row[1].tobytes())
print(row[0])