Find and Replace Data Source Across Multiple MXDs in a Folder

3645
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
TerryHiggins1
New Contributor III
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_


Thanks I am passing the parms through a GP tool. I will try hard coding to see if I can get this to work. Any suggestion on where to search to learn more about debugging why a parameter being passed via a GP tool isn't working correctly?
0 Kudos
LaurenYee
Occasional Contributor
Hi,
I asked a similar question here with the resulting code:

import os, arcpy

folderPath = "G:\GIS\Services\Test"
for fileName in [x for x in os.listdir(folderPath) if os.path.splitext(x)[1] == ".mxd"]:
    fullPath = os.path.join(folderPath, fileName)
    if os.path.isfile(fullPath):          
        mxd = arcpy.mapping.MapDocument(fullPath)
        print "MXD: " + fileName
        arcpy.env.workspace = fullPath            
        mxd.replaceWorkspaces("", "NONE", r"Database Connections\Connection to gisserver.sde","SDE_WORKSPACE")        

        mxd.save()
        del mxd
    else:
        print "error! {0} failed to be replaced".format(fullPath)
print "successfully changed data sources"
0 Kudos
RhettZufelt
MVP Frequent Contributor
Thanks I am passing the parms through a GP tool. I will try hard coding to see if I can get this to work. Any suggestion on where to search to learn more about debugging why a parameter being passed via a GP tool isn't working correctly?


I rarely use tools/models from within ArcMap other than to write my initial python code for me, so probably not the best to answer this question.

However, the few that I do run through ArcMap/Toolbox, I right-click on the model script itself, select properties, and parameters.  this is where you set the parameters that get passed to arcpy when run.  Can hard code, browse button, etc.

Another way to pass parameters is as arguments.   C:\pythonpath\python.exe scriptfile.py arg1 arg2 arg3  (which would be parameter(0), (1), etc).

However, I normally just hard code it in the python script, as it is either static, OR, python tools can iterate/parse/filter/etc. to get the paramaters I need.

R_
0 Kudos
TerryHiggins1
New Contributor III
I rarely use tools/models from within ArcMap other than to write my initial python code for me, so probably not the best to answer this question.

However, the few that I do run through ArcMap/Toolbox, I right-click on the model script itself, select properties, and parameters.  this is where you set the parameters that get passed to arcpy when run.  Can hard code, browse button, etc.

Another way to pass parameters is as arguments.   C:\pythonpath\python.exe scriptfile.py arg1 arg2 arg3  (which would be parameter(0), (1), etc).

However, I normally just hard code it in the python script, as it is either static, OR, python tools can iterate/parse/filter/etc. to get the paramaters I need.

R_


This is how I intially was passing the parameter, however I hard coded them as you suggested then ran the process. I did get the values I expected to print with the print statement but I still did not have the changes saved. The interesting thing - after I ran it the first time and then checked the mxd to see if the source was changed, and it wasn't I ran the process again. This time however the original datasource created a message stating it was not found. I am so baffled by this and not sure where to go next?
If the issue was a problem with how I wrote the save then running the script again should have still found the original datasource, but it didn't.

Any additional thoughts on this?
In the meantime I am gong to create a new test set and try the hard coded concept.
0 Kudos