3

I've written a tool that prompts the user for a directory path, and optionally a single mxd. It then crawls the directory for mxds (or just the single one) and writes some of the properties of the layers in each mxd to a csv file. Most of this works fine, except none of the data sources are listed.

I've seen Crawling directory and listing all datasources using ArcPy? but can't see where I am going wrong. The other properties are written just fine.


Modified the inner for loop a bit, just to see what was being found. The line:

arcpy.AddMessage('\ndataSource is: {0}'.format(lyr.dataSource))

does display the data source of all supported layers. Ran it on a larger set of mxds, with sde files, shapefiles, file gdb feature classes, web services and connections to servers, such as USDS and our own server. The only data sources that printed to the csv were for image files on the servers. The connections to these are in ArcCatalog, which is where I'm running the tool from.

import arcpy, os, fnmatch, csv

mxddirectory = arcpy.GetParameterAsText(0)
mxd_single = arcpy.GetParameterAsText(1)
outputcsvlocation = arcpy.GetParameterAsText(2)

mxd_list = []

if len(mxd_single) > 0:
    mxd_list.append(mxd_single)
else:
    for dirpath in os.walk(mxddirectory):
        for filename in dirpath[2]:
            if fnmatch.fnmatch(filename, '*.mxd'):
                mxd_list.append(os.path.join(dirpath[0], filename))

if len(mxd_list) > 0:
    outputcsv = open(outputcsvlocation, 'wb')
    writer = csv.writer(outputcsv, dialect = 'excel')

    writer.writerow(['Mxd path', 'Layer Name', 'Layer Description', 'Layer Source'])

    for mxdpath in mxd_list:
        mxdname = os.path.split(mxdpath)[1]

        try:
            mxd = arcpy.mapping.MapDocument(mxdpath)

            dfList = arcpy.mapping.ListDataFrames(mxd)

            for df in dfList:
            for lyr in arcpy.mapping.ListLayers(mxd, '', df):
                if lyr.supports('dataSource'):
                    arcpy.AddMessage('\ndataSource is: {0}'.format(lyr.dataSource))
                    layerattributes = [mxdpath.encode('utf8'), lyr.longName.encode('utf8'), lyr.description.encode('utf8'), lyr.dataSource.encode('utf8')]
                    writer.writerow(layerattributes)
                else:
                    arcpy.AddMessage('\nLayer {0} does not support dataSource.'.format(lyr.longName))

        except Exception as e:
            arcpy.AddMessage('EXCEPTION: {0}\n{1}\n{2}\n'.format(mxdpath, lyr.longName, e))

        writer.writerow(['', '', '', ''])

        del mxd

    outputcsv.close()

else:
    arcpy.AddError('No ArcMap documents found')
1

I figured out the error. The dataSource was in fact being written to the csv. But in most cases, the description property, while supported, had no value. Rather than printing an empty space, Null value or exception, the writer simply put the dataSource in the Layer Description column. I did not realize the csvwriter had this behavior.

0

I just tested your script replacing the parameters with the following:

mxddirectory = ""
mxd_single = r"C:\Scratch\mydoc.mxd"
outputcsvlocation = r"C:\scratch\aaa.csv"

The code ran without error and generated the expected output. So this leads me to ask are the MXD's you are trawling for data sources MXD's with broken links? I would imagine that would return nothing for the data sources?

  • No, no broken links. It correctly identifies unsupported data types, such as annotation. The lyr.description field looks like it has the data source path, but why no dataSource? – recurvata Oct 2 '15 at 17:52
0

You may have unicode characters in your layer names or layer descriptions.

So replace this line:

layerattributes = [mxdpath, lyr.longName, lyr.description, lyr.dataSource]

with

layerattributes = [mxdpath.encode('utf8'), lyr.longName.encode('utf8'), lyr.description.encode('utf8'), lyr.dataSource.encode('utf8')]
  • No, good idea, but no difference in the output. – recurvata Oct 2 '15 at 17:56
  • What error do you get? – Farid Cheraghi Oct 2 '15 at 18:04
  • No error. It just doesn't write out the data source. – recurvata Oct 2 '15 at 18:24
  • @recurvata, There is a try catch statement in your code. The error messages get printed in geoprocessing result window as error message. or you can instead remove the try catch and check the error. Another possbility is that none of your layers responds to "dataSource"! – Farid Cheraghi Oct 2 '15 at 18:41
  • Yes, but there are no errors, either in the addMessage window when the script runs or in results. Edited original post with some more info. – recurvata Oct 2 '15 at 18:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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