How to symbolize which features have attachments?

11548
15
11-19-2014 02:35 AM
TuridBrox
Occasional Contributor

Does anyone know if it's possible to symbolize which features have an attachment? I have a point feature class with an attachment table containing pictures. Only some of the points have attached pictures. I'd like to show with different symbols in the map which features have attachments and which have not.

So far, the best I've come up with is to join the feature class and the attachment table, and to symbolise on one of the attributes in the attachment table. Where the attribute is <null>, there is no attachment. This is not a good solution, because the join seems to make it impossible for me to add new attachments to the feature class. I have therefore exported the table containing the join, but that means the symbology is static.

15 Replies
NeilAyres
MVP Alum

Very good question, and no obvious answers.

I will look forward to some more enlightened answers than mine.

RachelHappeny
New Contributor

To clarify your point feature has some identifying attribute, such an account number let's say. This account number is also in your table that has the pictures and the pictures are in the table as a file pathway link. Is this correct? If so may I ask why your point feature attribute table does not have the file pathway in it and why it is in a separate table? If it was in your point feature you could hyperlink to the photos.

0 Kudos
TuridBrox
Occasional Contributor

That's a good point, Rachel. I've used a standard feature in ArcSDE databases called Create Attachments. This creates a related table for a feature class with geometry (such as our point feature class), and the pictures are stored in the related table - as you correctly surmised. I guess it works in this way so people don't have to change the schema of their original feature class. The two are related via the object id in the original feature class. BTW the pictures are not linked to with a pathway, they reside in the database as blob features.

0 Kudos
XanderBakker
Esri Esteemed Contributor

I guess you would need a physical field in you attribute table that indicates if the feature has an attachment. You could do the following:

  • add a new field
  • calculate the field like this:

CalculateAttachments.png

This is the code used:

def hasAttachment(oid):
    fc = r"D:\Xander\GeoNet\Attachments\test.gdb\test"
    att = "{0}__ATTACH".format(fc)
    fld_reloid = "REL_OBJECTID"
    lst_relOID = list(set([r[0] for r in arcpy.da.SearchCursor(att, (fld_reloid))]))
    return 1 if oid in lst_relOID else 0

The bad thing is that you would have to change the reference on line 2 where the path and name of the featureclass is indicated (I don't know how to access the path to the fc from the field calculator). The other thing is that every time you update attachments, you will have to recalculate. You will need to be in an edit session to calculate the field.

The result is a field that has value 1 for those features with attachments and value 0 for those that don't.

Kind regards, Xander

NeilAyres
MVP Alum

How fast does that go Xander.?

As I understand it, you are running a search cursor over the attachment table for every oid in the primary Fc.

It would probably be better to write an updating script which reads the attachment table once, stores the results in a list or dict, then looks through the fc to update. But this would not be implementable in the field calculator. But good thinking.

Perhaps there is an "idea" here to make symbolization of records with / without attachments easier.

XanderBakker
Esri Esteemed Contributor

You are absolutely right. It would be better to create a tool and use the arcpy.da.UpdateCursor to update the featureclass based on a list (dictionary is not necessary) with REL_OBJECTID's from the attachment table.

0 Kudos
XanderBakker
Esri Esteemed Contributor

And to show an (untested) example of how that could be:

  • create a toolbox
  • add a script to the toolbox (see content below)
  • define first parameter as a featureclass
  • define second parameter as field, obtained from the fc in first parameter

Add the output field to the featureclass and run the tool.

import arcpy
def main():

    fc = arcpy.GetParameterAsText(0)
    fldname = arcpy.GetParameterAsText(1)

    lst_OIDs = createRelObjectidListAttachments(fc)

    flds = ("OID@", fldname)
    with arcpy.da.InsertCursor(fc, flds) as curs:
        for row in curs:
            row[1] = 1 if row[0] in lst_OIDs else 0
            curs.updateRow(row)

def createRelObjectidListAttachments(fc):
    att = "{0}__ATTACH".format(fc)
    fld_reloid = "REL_OBJECTID" 
    lst_relOID = list(set([r[0] for r in arcpy.da.SearchCursor(att, (fld_reloid))]))
    return lst_relOID

if __name__ == '__main__':
    main()

Be aware: the code has not been tested and and does not perform any error handling.

NeilAyres
MVP Alum

Just tried to implement this tool from Xander, thank you.

However, it won't work as stated. You can't iterate over an insert cursor.

It should be UpdateCursor, because we are updating an existing field.

XanderBakker
Esri Esteemed Contributor

You are absolutely right. Good catch!

0 Kudos