Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I want to batch replace paths in a series of .mxd files using Python. Many of the layers have moved and in some cases the name has changed or its dataset is different.

I've written this code which takes an Excel file with two columns (one column for the old path and one column for the new path) and converts to a dictionary. Then I iterate through the layers in my .mxd files, and iterate through the dictionary, using replaceDataSource to change the data sources.

The trouble is this won't work with annotation feature classes. I've added in a try/except with findAndReplaceWorkspacePath to see if that may work (I don't believe the annotation layers/names have changed), but the code still doesn't address those layers.

One thing to note is that the annotation feature classes are stored in a personal geodatabase, but I don't know if this could be causing any issues.

I am hoping someone has ideas on code that will work to change the path of the annotation feature classses!

Here is my code:

import xlrd, arcpy, os

mxd_path = r'C:\temp\Chapters'

d = {}
wb = xlrd.open_workbook('U:\GIS\Chevron_Lokern\Projects\Figures_Update_2014\Lokern_Source_Paths_KL.xls')
sh = wb.sheet_by_index(0)
for i in range(293):
  cell_value_class = sh.cell(i,0).value
  cell_value_id = sh.cell(i,1).value
  d[cell_value_class] = cell_value_id

  for dirpath, dirnames, filenames in os.walk(mxd_path):
    for filename in filenames:
      fullPath = os.path.join(dirpath, filename)
      if filename[-4:] == ".mxd":
        mxd = arcpy.mapping.MapDocument(fullPath)
        print filename

        for lyr in arcpy.mapping.ListLayers(mxd):
            if lyr.supports("DATASOURCE"):
                #print lyr.datasetName
                for k,v in d.iteritems():
                    #print k,v
                    k_path, k_name = os.path.split(k)
                    v_path, v_name = os.path.split(v)
                    if lyr.dataSource == k and k != v:
                        #print 'KEY:',k,'VAL:',v, 'NAME:',v_name
                            print 'trying to change data source for',lyr.dataSource
                        except Exception as e:
                            print 'can\'t replace',lyr.dataSource, e
                                print 'trying to change data source for',lyr.dataSource
                            except Exception as e:
                                print 'still can\'t replace',lyr.dataSource, e
                                    print 'trying to change data source for',lyr.dataSource
                                except Exception as e:
                                    print 'still can\'t replace',lyr.dataSource, e
                                        print 'trying to change data source for',lyr.dataSource
                                    except Exception as e:
                                        print 'can\'t replace workspace path for',lyr.datasetName, e
        mxd.relativePaths = 'True'
del mxd
share|improve this question
Annotation layers are unique. This is a method I used for accessing their datasource.… – Tom_s Apr 16 '14 at 21:59

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.