Naming images from batch attachment export from a layer field

1049
7
Jump to solution
11-01-2022 12:43 PM
Labels (3)
SRanseen
New Contributor III

Hi all.  I am not good at python at all. I have tried using other codes I found but am having no luck.  I am just not good enough to see what I need to change. 

I used the batch export attachment rules  and created the tool to export out the images but I need to have the images labeled with the asset_number from the layer so we don't have to go through and label each one individually.

I have GlobalID that create the relation between the tables but need the asset_number from the layer to be the actual image file name.

Any ideas?   I am working in pro 3.0

0 Kudos
1 Solution

Accepted Solutions
RhettZufelt
MVP Frequent Contributor

Below is what I am using.  I don't attach to a tool or anything.  I just hard code the feature class with attachments, and the attachemnt table.

 

import arcpy
import os

inFeatureClass = r'Database Connections\Database.sde\Database.DBO.Signs'         # feature class with attachments
pointFieldsList = ['GlobalID','asset_number']                 # fields to load into cursor

global_dict = {}                                           # dictionary to hold globalIDs and "name" field

fileLocation = r'C:\tmp\Attachments'                       # folder where attachments are saved MAKE SURE FOLDER EXISTS


with arcpy.da.SearchCursor(inFeatureClass, pointFieldsList) as point_cursor:  # cursor to make dict of globalID's
        for row in point_cursor:
          if row[1]:
            row1 = row[1]                                 # I'm using "asset_number" as my name field, but is
          else:                                           # not always populated.  if Null, substitute "NA"
            row1 = "NA"
          global_dict[row[0]] = [row[0],row1]             # add to dict with globallID as key, name as value


inTable = r'Database Connections\Database.sde\Database.DBO.Sign__ATTACH'   #  attachment table for feature class
tableFieldsList = ['REL_GLOBALID', 'DATA', 'ATT_NAME', 'ATTACHMENTID']              # field list in attachment table


with arcpy.da.SearchCursor(inTable, tableFieldsList) as table_cursor:
    for item in table_cursor:
        attachment = item[1]                                                        # grab attachemnt from blob field
        filename = global_dict[item[0]][1] + '_' + str(item[3]) + '.jpg'            # create filename from value in FC dict that has matching GlobalID
                                                                                    # added  '_' + str(item[3]) +  to add attachment ID as many of my names are the same
        open(fileLocation + os.sep + filename, 'wb').write(attachment.tobytes())    # write the attachment as a file.

 

If your asset_number is unique for all features, you could delete the "     + '_' + str(item[3])   " from line 28.  That just appends the attachment_id to the filename so that it is unique.

R_

 

View solution in original post

0 Kudos
7 Replies
RhettZufelt
MVP Frequent Contributor

Below is what I am using.  I don't attach to a tool or anything.  I just hard code the feature class with attachments, and the attachemnt table.

 

import arcpy
import os

inFeatureClass = r'Database Connections\Database.sde\Database.DBO.Signs'         # feature class with attachments
pointFieldsList = ['GlobalID','asset_number']                 # fields to load into cursor

global_dict = {}                                           # dictionary to hold globalIDs and "name" field

fileLocation = r'C:\tmp\Attachments'                       # folder where attachments are saved MAKE SURE FOLDER EXISTS


with arcpy.da.SearchCursor(inFeatureClass, pointFieldsList) as point_cursor:  # cursor to make dict of globalID's
        for row in point_cursor:
          if row[1]:
            row1 = row[1]                                 # I'm using "asset_number" as my name field, but is
          else:                                           # not always populated.  if Null, substitute "NA"
            row1 = "NA"
          global_dict[row[0]] = [row[0],row1]             # add to dict with globallID as key, name as value


inTable = r'Database Connections\Database.sde\Database.DBO.Sign__ATTACH'   #  attachment table for feature class
tableFieldsList = ['REL_GLOBALID', 'DATA', 'ATT_NAME', 'ATTACHMENTID']              # field list in attachment table


with arcpy.da.SearchCursor(inTable, tableFieldsList) as table_cursor:
    for item in table_cursor:
        attachment = item[1]                                                        # grab attachemnt from blob field
        filename = global_dict[item[0]][1] + '_' + str(item[3]) + '.jpg'            # create filename from value in FC dict that has matching GlobalID
                                                                                    # added  '_' + str(item[3]) +  to add attachment ID as many of my names are the same
        open(fileLocation + os.sep + filename, 'wb').write(attachment.tobytes())    # write the attachment as a file.

 

If your asset_number is unique for all features, you could delete the "     + '_' + str(item[3])   " from line 28.  That just appends the attachment_id to the filename so that it is unique.

R_

 

0 Kudos
SRanseen
New Contributor III

Thank you I was able to get it to work just running it in a notebook.

0 Kudos
AndrewHankinson
New Contributor III

Thank you @RhettZufelt this is exactly what I was looking for having just exported a whole host of attachments from a master layer of which none were directly relateable to the features. 

I have got the script to work so that the attachments exported contain a specific project name, however is it possible to have the exported attachments have a name like this. 

Project_name_Feature_ID_AttachmentID.jpg?

I have tried adding in 

pointFieldsList = ['GlobalID','PROJECT','Feature_ID']

But I'm thinking that I need to add something to the 

filename = global_dict[item[0]][1] + '_' + str(item[3]) + '.jpg'

Can you help me out?

0 Kudos
RhettZufelt
MVP Frequent Contributor

See this link for future code posting.  Makes it much easier to follow.

Do you have an attribute for each feature with the project or are all features in the featureclass from the same project?

If they are all the same project and you just want to modify the filename to add the project name to the beginning then this should do it:

pointFieldsList = ['GlobalID','Feature_ID']
filename = 'ProjName_' + str(global_dict[item[0]][1]) + '_' + str(item[3]) + '.jpg'

 

R_

0 Kudos
AndrewHankinson
New Contributor III

Hi @RhettZufelt, thanks for getting back to me so quickly.

Sorry I didn't know about that link, only just looking at using scripts in ArcGIS Pro recently. I think I need to set up python as my main script editor as I am currently only using notebooks.

Each feature will have a unique Feature_ID, the feature class is a master layer for multiple projects so there is an additional attribute called 'PROJECT'.

With your script above I can get the PROJECT as the file name followed by the attachment ID, what would be ideal is to have the PROJECT followed by the Feature_ID then thet attachment ID so each attachment can be traced back to the specific feature.

0 Kudos
RhettZufelt
MVP Frequent Contributor

this does that.  Had to change field name as my test dataset is based on OBJECTID, not GlobalID.

 

import arcpy
import os

inFeatureClass = r'Database Connections\database.sde\database.DBO.Imagery_Points_2024'         # feature class with attachments
pointFieldsList = ['OBJECTID','Feature_ID', 'PROJECT']                 # fields to load into cursor

global_dict = {}                                           # dictionary to hold OBJECTID and "name" field

fileLocation = r'C:\tmp\Attachments'                       # folder where attachments are saved MAKE SURE FOLDER EXISTS


with arcpy.da.SearchCursor(inFeatureClass, pointFieldsList) as point_cursor:  # cursor to make dict of OBJECTID's
        for row in point_cursor:
          if row[1]:
            row1 = row[1]                                 # I'm using "Feature_ID" as my name field, but is
          else:                                           # not always populated.  if Null, substitute "NA"
            row1 = "NA"
          global_dict[row[0]] = [row[0],[row1,row[2]]]             # add to dict with OBJECTID as key, name and project as value list


inTable = r'Database Connections\database.sde\database.DBO.Imagery_Points_2024__ATTACH'   #  attachment table for feature class
tableFieldsList = ['REL_OBJECTID', 'DATA', 'ATT_NAME', 'ATTACHMENTID']              # field list in attachment table


with arcpy.da.SearchCursor(inTable, tableFieldsList) as table_cursor:
    for item in table_cursor:
        attachment = item[1]                                                        # grab attachemnt from blob field
        filename = global_dict[item[0]][1][1] + '_' + global_dict[item[0]][1][0] + '_' + str(item[3]) + '.jpg'            # create filename from value in FC dict that has matching OBJECTID
        open(fileLocation + os.sep + filename, 'wb').write(attachment.tobytes())    # write the attachment as a file.

 

basically, it adds a list (Feature_ID, PROJECT) as the value in the dictionary key:value pair.

Then, extract the second value from the pair as the project name, first value of the pair is the Feature_ID.

I'm sure there's a better way to extract multiple values from a dictionary key, but no time to research it.

maybe someone on here can improve it.

R_

0 Kudos
AndrewHankinson
New Contributor III

@RhettZufelt , that's incredibly helpful thank you.

0 Kudos