Iterate Through MXDs to Change One Layer Data Source for Multiple MXDs

2174
13
03-18-2021 03:33 PM
rnaneliu
New Contributor

Hi,  I am trying to change the data source of our parcel fabric that is not being maintained to a new one stored in the same SDE dataset.  I have created a script to the best of my ability and I get this error.  I have searched for possible solutions all day.  I am sure it's a simple solution but this is time sensitive and I need to figure out what I am doing wrong as soon as possible.  Thanks for any help you can offer. 

ERROR:

if lyr.name == "Fernie Parcel":
NameError: name 'lyr' is not defined

---------------------------------------------------------------------------------------------------------------------------------------

import arcpy
from arcpy import env
from arcpy import mapping
arcpy.env.workspace = workspace = r"P:\mxd_data_source"

arcpy.env.overwriteOutput = True

mxdList = arcpy.ListFiles("*.mxd")

for mxd in mxdList:
mxd = workspace + "\\" + mxd
print mxd + " is being processed"
mxd = arcpy.mapping.MapDocument(mxd)
for df in arcpy.mapping.ListDataFrames(mxd, "*"):
if lyr.name == "Fernie Parcel":
lyr.replaceDataSource(workspace, "SDE_WORKSPACE", "parcel_pmbc", validate=True)
print "Successfully updated data sources"
mxd.save()

0 Kudos
13 Replies
by Anonymous User
Not applicable

It doesn’t look like you have iterated over any layers in your mxd yet ...

for lyr in arcpy.mapping.ListLayers(df):

so it’s saying it can’t find ‘lyr’

rnaneliu
New Contributor

Thanks Jeff,

I entered the line. It said it works but the link is broken and points to P:\mxd_data_source as being my database.  Instead of my SDE.  I am guessing I need to run another broken link script.  Cheers!

Data Source

Data Type: SDE Feature Class
Feature Class: parcel_pmbc
Database: P:\mxd_Data_source
Feature Dataset: xxxx.SDE.Parcels
Feature Type: Simple
Geometry Type: Polygon

New Script

import arcpy
from arcpy import env
from arcpy import mapping
arcpy.env.workspace = workspace = r"P:\mxd_data_source"

arcpy.env.overwriteOutput = True

mxdList = arcpy.ListFiles("*.mxd")

for mxd in mxdList:
mxd = workspace + "\\" + mxd
print mxd + " is being processed"
mxd = arcpy.mapping.MapDocument(mxd)

for df in arcpy.mapping.ListDataFrames(mxd, "*"):
for lyr in arcpy.mapping.ListLayers(df):
if lyr.name == "Fernie Parcel":
lyr.replaceDataSource(workspace, "SDE_WORKSPACE", "parcel_pmbc", validate=True)
print "Successfully updated data sources"
mxd.save()

0 Kudos
by Anonymous User
Not applicable

Are you running this script while the mxd is open or closed?

0 Kudos
rnaneliu
New Contributor

Hi Jeff,  All mxds are closed.  There are 180 mxds.  I did this in a test folder for now.

Cheers,

0 Kudos
by Anonymous User
Not applicable

Ok, According to the replaceDataSource method docs, the first parameter in the method is the workspace you want it to be changed to.  Assign pathToSDEConnection  to your sde connection file.

try this:

arcpy.env.workspace = workspace = r"P:\mxd_data_source"
pathToSDEConnection = r'Path to your connection file'

# arcpy.env.overwriteOutput = True
mxdList = arcpy.ListFiles("*.mxd")

for mxd in mxdList:
    mxdpath = workspace + "\\" + mxd
    print mxd + " is being processed"

    mxdMd = arcpy.mapping.MapDocument(mxdpath)

    for df in arcpy.mapping.ListDataFrames(mxdMd, "*"):
        for lyr in arcpy.mapping.ListLayers(df):
            print lyr.name
            if lyr.name == "Fernie Parcel":
                arcpy.AddMessage("Updating connections: {}".format(lyr.name))
                lyr.replaceDataSource(pathToSDEConnection, "SDE_WORKSPACE", "parcel_pmbc", validate=True)

    mxdMd.save()
    print("Done updating data sources in {}".format(mxd))

 

0 Kudos
rnaneliu
New Contributor

We are getting there!!  It works beautifully for the first mxd.  Then I get an unexpected error: ValueError: Layer: Unexpected error Database Platform: SQL Server.  This is when I have the validate set to True.  When I change it to False,  It runs through all the mxds successfully but my links are broken except for the first one which works.  Cheers!

First successful mxd data source:

Data Type:       SDE Feature Class

Database Platform:     SQL Server

Server: sql

Connection Properties:            sql

Authentication Type:  Operating system authentication

Database:        C

Version:           sde.DEFAULT

Description:     Instance default version.

Feature Dataset:          C.SDE.Base

Feature Class:  C.SDE.parcel_pmbc

Feature Type:  Simple

Geometry Type:          Polygon

Coordinates have Z values:     Yes

Coordinates have measures:    No

Second mxd data source

Data Type: SDE Feature Class
Feature Class: parcel_pmbc
SERVER: sql
INSTANCE: sde:sqlserver:sql
DBCLIENT: sqlserver
DB_CONNECTION_PROPERTIES: sql
Database: C
IS_GEODATABASE: true
AUTHENTICATION_MODE: OSA
CONNPROP-REV: Rev1.0
VERSION: sde.DEFAULT
Feature Dataset: C.SDE.Base
Feature Type: Simple
Geometry Type: Polygon

 

0 Kudos
by Anonymous User
Not applicable

Are they different datasources between the mxds? The first one pointing to your workspace and the others pointing to a dataset in a SQL server?  I can't tell if this will work because I don't know all your datasource paths but if they are different you will have to test and process those separately. For example, testing for the 'workspace' path in the datasource:

 

arcpy.env.workspace = workspace = r"P:\mxd_data_source"
arcpy.env.overwriteOutput = True
mxdList = arcpy.ListFiles("*.mxd")

for mxd in mxdList:
    mxdpath = workspace + "\\" + mxd
    print mxd + " is being processed"

    mxdMd = arcpy.mapping.MapDocument(mxdpath)

    for df in arcpy.mapping.ListDataFrames(mxdMd, "*"):
        for lyr in arcpy.mapping.ListLayers(df):
            if lyr.name == "Fernie Parcel":
                if lyr.supports("DATASOURCE"):
                    if workspace in lyr.dataSource:
                        print "Updating connections: {}".format(lyr.name)
                        lyr.replaceDataSource(workspace, "SDE_WORKSPACE", "parcel_pmbc", validate=True)
                else:
                    print "{} in {} does not support Datasource.".format(lyr.name, mxd)

    mxdMd.save()
    print("Done updating data sources in {}".format(mxd))

 

 

0 Kudos
rnaneliu
New Contributor

Hi Jeff,

The workspace is where my mxds are sitting. 

The two feature classes that I am working with are in the same dataset in the SDE.  Database Connections\User on DEFAULT.sde\COF.SDE.Base.  Thanks,

0 Kudos
rnaneliu
New Contributor

I ran a the script to list layer source.  The sources do point to this data source originally if that helps.  This is a learning experience, thank you!

C:\Users\username.CF\AppData\Roaming\ESRI\Desktop10.4\ArcCatalog\CF on SQL-DEFAULT.sde\CF.SDE.Base

0 Kudos