Hi Ian,
Thanks. Basically, all my map documents have a broken link now for that picture element. Since the directory was changed, \\Jackson\gis_dept\Data\Images\County-logo-1x1Small.JPG" is a dead path. As you said, I could update the path manually, but it's too time consuming.
If and when I find a method to fix broken picture links and then repair them I'll post it.
Is the path for all the broken pictures the one you noted above? It would be fairly easy to have a script walk through all the map documents in a directory and replace all the picture elements with that specific path with a new path.
Also I noted something fairly interesting, when a link is working to an picture element, the element name is just the name of the image itself without the file extension, whereas when I opened your map with broken links, the name was now the filepath to where the image was, instead of just the file name.
The reason your script wasn't changing anything was because as I noted above the image name was no longer just the file name of the picture, but the full path to the picture. I used the python window in the map document and managed to change your picture element to a site plan jpg on my desktop. Your code would have worked fine, but since the elm.name wasn't what you thought it was, it actually didn't change anything.
If that is the particular path you need to replace on all your mxds, here is some starter script to get you going on editting them all. This should walk through all the .mxd files in a workspace and any .mxds in any folders within that workspace, check for picture elements with the broken file name and fix to your new image. I would take 2 or 3 map documents into a separate folder to test this. Only thing you need to do is change the workspace to the folder where the map documents are.
import arcpy
from arcpy import env
#Change to Directory with you map documents,
env.workspace = r"YourDirectoryHere"
#Recursively walking workspace
for root, dirs, files in os.walk(env.workspace):
for f in files:
if f.endswith(".mxd"):
mxd = arcpy.mapping.MapDocument(os.path.join(root , f))
print "Current map being checked is " + mxd.filepath
for elem in arcpy.mapping.ListLayoutElements(mxd, "PICTURE_ELEMENT", "*logo")):
if elem.name == r"\\Jackson\gis_dept\Data\Images\County-logo-1x1Small.JPG":
elem.sourceImage = r"P:\Images\County-logo.JPG"
del elem
del mxd
That looks great. But, it's giving me an error. Also, i'm curious why your line 13 is indented? That was giving me an error before i dedented.
apologies, it should be filePath, not filepath. I didn't test it, just cobbled it together from the python interpreter and some old code I had to check for broken data links.
I added the print statements so you knew what was going on with the program. They are also a great way to see what values are actually being used in python and make sure they are doing what you want. Thats how I figured out your elm.name value earlier wasn't the right one for your code to work.
Not sure about line 13, whitespace can be annoying to work with, especially when cutting/pasting code, like I said I cobbled it together quickly.
Ok, thanks. I fixed 'mxd.filePath'. The script ran with no errors and printed out "Current map being checked is..." for all the documents in the workspace, but with no results.
Above in your test script you used \\Jackson\gis_dept\Data\Images\County-logo-1x1Small.JPG as your elem.name path and it worked. Does this mean it doesn't have to be a working file path? Of course, since that's a path to our directory here you can't access it. But, at the same time the Jackson network was discontinued a few days ago (hence the broken links). Or is the script recognizing that file path as the element name?
This is the message from Windows when I search for it:
So, I'm wondering if that's causing a problem in my script?
Besides that I set the workspace to a working folder. And I used the whole path, as you did, for the elem.name:
import arcpy
import os
from arcpy import env
# change to directory with your map documents
env.workspace = r'R:\AtlasMaps\ATLAS_MAPS_17\New folder'
# recursively walking workspace
for root, dirs, files in os.walk(env.workspace):
for f in files:
if f.endswith(".mxd"):
mxd = arcpy.mapping.MapDocument(os.path.join(root , f))
print "Current map being checked is " + mxd.filePath
for elem in arcpy.mapping.ListLayoutElements(mxd, "PICTURE_ELEMENT", "*logo"):
if elem.name == r"\\Jackson\gis_dept\Data\Images\County-logo-1x1Small.JPG":
elem.sourceImage = r"P:\Images\County-logo.JPG"
del elem
del mxd
The filepath doesn't have to exist, it just had to be the value of the element name in the map drawing. If you looked at the image I posted earlier using the mxd you posted, I used print statements to determine what the actual name of the picture element was in the map drawing.
Also I noticed another bug that might be causing the issue, line 13 needs an asterisk on the other side of logo, so it should be:
for elem in arcpy.mapping.ListLayoutElements(mxd, "PICTURE_ELEMENT", "*logo*"):
If it doesn't have a wildcard on both sides, it might not be pulling any picture elements at all, so it has no elements to even check(Since *logo would only find names ending with logo, instead of *logo* which looks to find names that contain the character string logo). If that doesn't work, could you add a few print statements(even if it does work it helps show what is going on). After line 13, could you add:
print "current element name is " + elem.name; print "current element source is " + elem.sourceImage
(same indent as line 14 currently).
Then after the current line 15 add:
print "new element source is " + elem.sourceImage
(same indent as line 15 currently)
Alright, great. At some point during testing I did try the asterisk on both sides of logo.
I added the print statements and the asterisk. It ran with no errors, but no results to the map document again. I double checked and both instances of the JPG in the maps of the workspace are exactly: \\Jackson\gis_dept\Data\Images\County-logo-1x1Small.JPG.
import arcpy
import os
from arcpy import env
# change to directory with your map documents
env.workspace = r'R:\AtlasMaps\ATLAS_MAPS_17\New folder'
# recursively walking workspace
for root, dirs, files, in os.walk(env.workspace):
for f in files:
if f.endswith(".mxd"):
mxd = arcpy.mapping.MapDocument(os.path.join(root, f))
print "current map being checked is " + mxd.filePath
for elem in arcpy.mapping.ListLayoutElements(mxd, "PICTURE_ELEMENT", "*logo*"):
print "current element name is " + elem.sourceImage
if elem.name == r"\\Jackson\gis_dept\Data\Images\County-logo-1x1Small.JPG": #\\Jackson\gis_dept\Data\Images\County-logo-1x1Small.JPG
elem.sourceImage = r"P:\Images\County-logo-1x1Small.JPG"
print "new element source is " + elem.sourceImage
del elem
del mxd
I'm going to try with some different maps that have the have the same broken link to Jackson.
Okay, so I'm a bit of an idiot, I didn't bother to have the script actually save the map after the changes were made. According to the the print statements the script is changing the source of your image, which is what we wanted, but the map document is not being saved with the changes. Since I originally did this in ArcMap python window, I didn't need to save the map, I just refreshed the view to fix the changes.
Just add mxd.save() to line 18 with the same indent as line 11 and that should save the changes......
Brilliant! Works like a charm. Thanks for the help man.