Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

After reorganizing the file structure for some of our GIS base data files I need a script to update the data sources for ~ 100 shapefiles in about 50 mxd files. Some of the mxds have multiple data frames. I have a list of the shapefile names and their new file paths that I'd like to use in a dictionary to define the workspace_path parameter in the lyr.replaceDataSource method.

After researching on this forum and others, I put together the code below, which runs smoothly (i.e., no errors and returns the "Workspace path is updated" print statement for each of the 3 layers in each dataframe) but the datasources are not actually updated when I open the map.

I'm relatively new to Python so maybe I'm missing something obvious here. Any insights or suggestions would be greatly appreciated.

#Select map
map_path = r'C:\Test\0102HomeRangeCopy.mxd'

#define dictionary

PathDict = {
    "SouthCarolina_SMA_geoN83_line": r"R:\Data\GIS\ManagedAreas\SMA",
    "SEUS_SMA_Offshore_line_geo": r"R:\Data\GIS\ManagedAreas\SMA",
    "LocalPorts_Alb": r"R:\Data\GIS\Shipping\Ports"}

import arcpy

mxd = arcpy.mapping.MapDocument(map_path)

for df in arcpy.mapping.ListDataFrames(mxd):
    for lyr in arcpy.mapping.ListLayers(mxd,"",df):
        layername = lyr.datasetName
        if layername in PathDict.keys():
            new_path = PathDict[layername]
            lyr.replaceDataSource(new_path,"SHAPEFILE_WORKSPACE", str(lyr.datasetName))
            if lyr.workspacePath == new_path:
                print "Workspace path for " + layername + " is updated."
            else:
               print "Path not updated for " + lyr.datasetName

mxd.save()
print "Map Saved"
del mxd

Here are some additional notes:

  • If I run the lyr.replaceDataSource method on its own for an individual file in the Python window as in the ArcGIS resources example, the datasource is updated as expected. It seems as though the issue might be with using the dictionary to define the parameters for different shapefiles or with iterating through the dataframes and layers

  • I've tested the the layers to ensure that the DATASOURCE and WORKSPACEPATH features are supported

  • The files are on a network and I've tried using UNC file paths, but this does not make a difference

  • none of the shapefile names have been changed

  • I'd like to avoid using lyr.findAndReplaceWorkspacePath so that I don't have to define the old path names in addition to the new path names for each shapefile

  • I'm working in Arc 10.0 service pack 4 on a Windows 7 64-bit machine


Thanks for your suggestions everyone!

After seeing that @blah238 could run the script in 10.1, I tried updating to service pack 5 and that solved the problem.

share|improve this question
    
Does the saveACopy(file_name, {version}) method work? –  Jason Oct 29 '12 at 18:59
    
Perhaps add/modify a print statement to report the actual new_path being used in each iteration - just in case its not getting pulled from the dictionary the way you think. Forward slash rather than backslash with raw may or may not make a difference. –  PolyGeo Oct 29 '12 at 21:03
add comment

1 Answer

Works fine for me at 10.1. I made a slight modification (other than the obvious configuration variable changes) for the case when the Layer.datasetName property is not supported:

#Select map
map_path = r"C:\GISData\BloomfieldTownship\BloomfieldTownship.mxd"

#define dictionary

PathDict = {
    "SiteAddress": r"C:\GISData\BloomfieldTownship",
    "RoadCenterline": r"C:\GISData\BloomfieldTownship",
    "SchoolTaxDistrict": r"C:\GISData\BloomfieldTownship"}

import arcpy

mxd = arcpy.mapping.MapDocument(map_path)

for df in arcpy.mapping.ListDataFrames(mxd):
    for lyr in arcpy.mapping.ListLayers(mxd,"",df):
        layername = lyr.datasetName if lyr.supports("datasetName") else ""
        if layername in PathDict.keys():
            new_path = PathDict[layername]
            lyr.replaceDataSource(new_path,"SHAPEFILE_WORKSPACE", layername)
            if lyr.workspacePath == new_path:
                print "Workspace path for " + layername + " is updated."
            else:
               print "Path not updated for " + layername
mxd.save()
print "Map Saved"
del mxd
share|improve this answer
add comment

Your Answer

 
discard

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.