Find and Replace Data Source Across Multiple MXDs in a Folder

3564
13
06-05-2013 01:28 PM
TerryHiggins1
New Contributor III
Ok - I'm a beginner trying to figure out how to modify one of the scripts I located. The original script is designed to search a folder with MXDs and print out report off all the MXDs that contain a particular data source. I want to take this one step further - so if the data source is located then I would like to replace it. I tried adding this to the sample code -

lyr.findAndReplaceWorkspacePath("dateSource", "newSource") #TH Testing
mxd.save() #TH Testing

The script runs but the change doesn't take place or if it does it isn't saved.
Any help would be great.


# Author:  ESRI
# Date:    July 5, 2010
# Version: ArcGIS 10.0 Final
# Purpose: This script will iterate through each MXD in a folder and report the
#          name of each map document that contains a specific data source.  The
#          script is intended to run from a script tool that requires three
#          input parameters:
#               1) A folder that contains the set of MXDs that will be searched,
#               2) A data source that you want to search for,
#               3) An output text file.
#          The resulting text file will automatically open.

import arcpy, datetime, os

try:

  #Read input parameters from GP dialog
  folderPath = arcpy.GetParameterAsText(0)
  dataSource = arcpy.GetParameterAsText(1)
  output = arcpy.GetParameterAsText(3)
  newSource = arcpy.GetParameterAsText(2)

  #Create an output file
  outFile = open(output, "w")

  #Report header
  outFile.write("Data Source Report: \n")
  outFile.write("\n")
  outFile.write("This report summarizes the names of all map documents within a folder that\n")
  outFile.write("contain a specific data source. \n")
  outFile.write("\n")
  outFile.write("Folder location: " + folderPath + "\n")
  outFile.write("\n")
  outFile.write("Date: " + str(datetime.datetime.today().strftime("%B %d, %Y")) + "\n")

  #Loop through ech MXD file
  mCnt = 0
  for filename in os.listdir(folderPath):
    fullpath = os.path.join(folderPath, filename)
    if os.path.isfile(fullpath):
      if filename.lower().endswith(".mxd"):
      
        #Reference MXD
        mxd = arcpy.mapping.MapDocument(fullpath)
       
        #Determine if the data source exists within the data frames/map document 
        #If exist then update the datasource - TH Testing 06/05/2013
        sCnt = 0
        for df in arcpy.mapping.ListDataFrames(mxd):
          layerList = []
          for lyr in arcpy.mapping.ListLayers(mxd, "", df):
            if lyr.supports("dataSource"):
              if lyr.dataSource == dataSource:
                lyr.findAndReplaceWorkspacePath("dateSource", "newSource") #TH Testing
                mxd.save() #TH Testing
                mCnt = 1
                sCnt = sCnt + 1
                layerList.append(lyr.name)
                if sCnt == 1:  #Write the MXD header once
                  outFile.write("\n")
                  outFile.write("\n")
                  outFile.write("---------------------------------------------------------------------------------- \n")
                  outFile.write(" MAPDOCUMENT: " + os.path.basename(mxd.filePath) + "\n")
                  outFile.write("---------------------------------------------------------------------------------- \n")
                  sCnt = sCnt + 1 
          if len(layerList) > 0: #Write the data frame name once
            outFile.write("\n")
            outFile.write("\t Data Frame: " + df.name + "\n")
            for lyr in layerList: #Write each layer name
              outFile.write("\n")
              outFile.write("\t\t Layer: " + lyr + "\n")

        del mxd
                      
  if mCnt == 0:
    outFile.write("\n")
    outFile.write("\n")
    outFile.write("---------------------------------------------------------------------------------- \n")
    outFile.write("              NO DATA SOURCES FOUND \n")
    outFile.write("---------------------------------------------------------------------------------- \n")
  outFile.close()

  #Open the resulting text file
  os.startfile(output)

  #Delete variable references
  del folderPath, dataSource, output, outFile, fullpath

except Exception, e:
  import traceback
  map(arcpy.AddError, traceback.format_exc().split("\n"))
  arcpy.AddError(str(e))
Tags (2)
0 Kudos
13 Replies
RhettZufelt
MVP Frequent Contributor
I have not tried this with python, however, there is/was a bug in the Set Data Source(s) in ArcGIS.  Don't know if it applies to the arcpy tool as well, but, if your data is UNC pathed, the Set Data Source does not work correctly.

Not anywhere I can test to see if they have fixed this yet, but thought I'd throw it out there in case you are using UNC paths,


R_
0 Kudos
JeffBarrette
Esri Regular Contributor
You are not saving the changes to the mxd.

Try:
mxd.save()
or
mxd.saveACopy(new path)

These lines would need to be at the same indent space as the mxd variable.

Jeff
0 Kudos
TerryHiggins1
New Contributor III
Jeff thank you for the response - however I thought this line that I inserted is handling the save?
lyr.findAndReplaceWorkspacePath("dateSource", "newSource") #TH Testing
                mxd.save() #TH Testing
0 Kudos
RhettZufelt
MVP Frequent Contributor
Ok - I'm a beginner trying to figure out how to modify one of the scripts I located. The original script is designed to search a folder with MXDs and print out report off all the MXDs that contain a particular data source. I want to take this one step further - so if the data source is located then I would like to replace it. I tried adding this to the sample code - 

lyr.findAndReplaceWorkspacePath("dateSource", "newSource") #TH Testing 
mxd.save() #TH Testing 

The script runs but the change doesn't take place or if it does it isn't saved. 
Any help would be great.  


# Author:  ESRI
# Date:    July 5, 2010
# Version: ArcGIS 10.0 Final
# Purpose: This script will iterate through each MXD in a folder and report the
#          name of each map document that contains a specific data source.  The
#          script is intended to run from a script tool that requires three
#          input parameters:
#               1) A folder that contains the set of MXDs that will be searched,
#               2) A data source that you want to search for,
#               3) An output text file.
#          The resulting text file will automatically open.

import arcpy, datetime, os

try:

  #Read input parameters from GP dialog
  folderPath = arcpy.GetParameterAsText(0)
  dataSource = arcpy.GetParameterAsText(1)
  output = arcpy.GetParameterAsText(3)
  newSource = arcpy.GetParameterAsText(2)

   #Loop through ech MXD file
  mCnt = 0
  for filename in os.listdir(folderPath):
    fullpath = os.path.join(folderPath, filename)
    if os.path.isfile(fullpath):
      if filename.lower().endswith(".mxd"):
      
        #Reference MXD
        mxd = arcpy.mapping.MapDocument(fullpath)
       
        #Determine if the data source exists within the data frames/map document 
        #If exist then update the datasource - TH Testing 06/05/2013
        sCnt = 0
        for df in arcpy.mapping.ListDataFrames(mxd):
          layerList = []
          for lyr in arcpy.mapping.ListLayers(mxd, "", df):
            if lyr.supports("dataSource"):
              if lyr.dataSource == dataSource:
                lyr.findAndReplaceWorkspacePath("dateSource", "newSource") #TH Testing
                mxd.save() #TH Testing
                mCnt = 1
                sCnt = sCnt + 1
))


Perhaps its due to trying to set it to a variable that hasn't been defined?

Not sure the exact syntax for that command, but dateSource <> dataSource

R_
0 Kudos
TerryHiggins1
New Contributor III
Perhaps its due to trying to set it to a variable that hasn't been defined?

Not sure the exact syntax for that command, but dateSource <> dataSource

R_


Thanks I didn't catch that typo. Those seem to get me! Will give it a try. Thanks again.
0 Kudos
TerryHiggins1
New Contributor III
Thanks I didn't catch that typo. Those seem to get me! Will give it a try. Thanks again.


Ok I corrected the syntax in regards to the typo. The script ran and correctly produced the report identifying the mxd within the folder with the datasource specified - however it did not update the data source. Any additional ideas on what I might be missing here?
0 Kudos
RhettZufelt
MVP Frequent Contributor
import arcpy, datetime, os

try:

  #Read input parameters from GP dialog
  folderPath = arcpy.GetParameterAsText(0)
  dataSource = arcpy.GetParameterAsText(1)
  output = arcpy.GetParameterAsText(3)
  newSource = arcpy.GetParameterAsText(2)

 

 print  folderPath
 print  dataSource
 print  output 
 print  newSource   

#Loop through ech MXD file
  mCnt = 0
  for filename in os.listdir(folderPath):
    fullpath = os.path.join(folderPath, filename)
    if os.path.isfile(fullpath):
      if filename.lower().endswith(".mxd"):
      
        #Reference MXD
        mxd = arcpy.mapping.MapDocument(fullpath)
       
        #Determine if the data source exists within the data frames/map document 
        #If exist then update the datasource - TH Testing 06/05/2013
        sCnt = 0
        for df in arcpy.mapping.ListDataFrames(mxd):
          layerList = []
          for lyr in arcpy.mapping.ListLayers(mxd, "", df):
            if lyr.supports("dataSource"):
              if lyr.dataSource == dataSource:
                lyr.findAndReplaceWorkspacePath("dateSource", "newSource") #TH Testing
                mxd.save() #TH Testing
                mCnt = 1
                sCnt = sCnt + 1
))


Are you sure your variables are getting set correctly? What happens if you add the changes above in blue?

R_
0 Kudos
TerryHiggins1
New Contributor III
import arcpy, datetime, os

try:

  #Read input parameters from GP dialog
  folderPath = arcpy.GetParameterAsText(0)
  dataSource = arcpy.GetParameterAsText(1)
  output = arcpy.GetParameterAsText(3)
  newSource = arcpy.GetParameterAsText(2)

 

 print  folderPath
 print  dataSource
 print  output 
 print  newSource   

#Loop through ech MXD file
  mCnt = 0
  for filename in os.listdir(folderPath):
    fullpath = os.path.join(folderPath, filename)
    if os.path.isfile(fullpath):
      if filename.lower().endswith(".mxd"):
      
        #Reference MXD
        mxd = arcpy.mapping.MapDocument(fullpath)
       
        #Determine if the data source exists within the data frames/map document 
        #If exist then update the datasource - TH Testing 06/05/2013
        sCnt = 0
        for df in arcpy.mapping.ListDataFrames(mxd):
          layerList = []
          for lyr in arcpy.mapping.ListLayers(mxd, "", df):
            if lyr.supports("dataSource"):
              if lyr.dataSource == dataSource:
                lyr.findAndReplaceWorkspacePath("dateSource", "newSource") #TH Testing
                mxd.save() #TH Testing
                mCnt = 1
                sCnt = sCnt + 1
))


Are you sure your variables are getting set correctly? What happens if you add the changes above in blue? 

R_


I entered in the lines you recommended however none of them printed... not sure what I am doing incorrect.
0 Kudos
RhettZufelt
MVP Frequent Contributor
It is not getting your parameters, are you passing them along with the command line.

If you are not running from a GP tool, you need to either pass the parameters as arguments (Python D:\scriptfile.py d:\myfolder myData OutPut NewSource) or code the paths (folderPath=r"C:\arcgisserver\local_data\").

I normally just put the path to my data in the script and run it.

R_
0 Kudos