I want to loop many mxds within a folder to retrieve layer,connection,etc. information using python.
I just need the syntax for looping through the mxds.
Hi Devin
I wrote the following python script to copy the datasets (feature classes & rasters) for each mxd within a folder into a new File Geodatabase. You could use the following as a starting point and instead of copy it out write the location of the layers (feature classes and rasters) into a summary table.
'''
Created on Jan 20, 2016
Copy all feature classes and
rasters from each mxd in a folder
into a new File Geodatabase.
@author: PeterW
'''
import os
import time
import arcpy
# set arguments
folder = arcpy.GetParameterAsText(0)
out_gdb = arcpy.GetParameterAsText(1)
# folder = arcpy.GetParameterAsText(0)
# out_gdb = arcpy.GetParameterAsText(1)
# Processing time
def hms_string(sec_elapsed):
h = int(sec_elapsed / (60 * 60))
m = int(sec_elapsed % (60 * 60) / 60)
s = sec_elapsed % 60
return "{}h:{:>02}m:{:>05.2f}s".format(h, m, s)
start_time1 = time.time()
# copy layers function
def copy_features():
try:
if arcpy.Exists(os.path.join(out_gdb, layer.datasetName)):
arcpy.AddMessage("Feature class already exists, it will be skipped")
else:
arcpy.FeatureClassToGeodatabase_conversion(lyr_source, out_gdb)
except:
arcpy.AddMessage("Error copying: " + layer.name)
arcpy.AddError(arcpy.GetMessages())
def copy_rasters():
try:
if arcpy.Exists(os.path.join(out_gdb, layer.datasetName)):
arcpy.AddMessage("Raster already exists, it will be skipped")
else:
out_raster = os.path.join(out_gdb, layer.datasetName)
arcpy.CopyRaster_management(lyr_source, out_raster)
except:
arcpy.AddMessage("Error copying: " + layer.name)
arcpy.AddError(arcpy.GetMessages())
# Loop through each data frame, layer and copy to new file geodatabase
for filename in os.listdir(folder):
fullpath = os.path.join(folder, filename)
if os.path.isfile(fullpath):
basename, extension = os.path.splitext(fullpath)
if extension.lower() == ".mxd":
arcpy.AddMessage("Processing: " + basename)
mxd = arcpy.mapping.MapDocument(fullpath)
dfs = arcpy.mapping.ListDataFrames(mxd)
for df in dfs:
arcpy.AddMessage("DataFrame: " + df.name)
layers = arcpy.mapping.ListLayers(mxd, "", df)
for layer in layers:
if layer.isFeatureLayer:
lyr_source = layer.dataSource
lyr_name = layer.name.encode("utf8", "replace")
arcpy.AddMessage("Copying: {}".format(lyr_name))
copy_features()
if layer.isRasterLayer:
lyr_source = layer.dataSource
lyr_name = layer.name.encode("utf8", "replace")
arcpy.AddMessage("Copying: {}".format(lyr_name))
copy_rasters()
# Determine the time take to copy features
end_time1 = time.time()
print ("It took {} to copy all layers to file geodatabase".format(hms_string(end_time1 - start_time1)))Let me know if you need help amending the following to meet you needs.
This is what worked for me. I used only what I needed and added openpyxl so I can write to excel. Yet I am still working on it successfully writing to excel
#Import Modules
import arcpy,os
from openpyxl import Workbook
#Set folder space
folder = xxxxx
#Set variables
# create excel worksheets
wb = Workbook()
ws1 = wb.create_sheet("yyy")
for filename in os.listdir(folder):
fullpath = os.path.join(folder, filename)
if os.path.isfile(fullpath):
basename, extension = os.path.splitext(fullpath)
if extension.lower() == ".mxd":
arcpy.AddMessage("Processing: " + basename)
mxd = arcpy.mapping.MapDocument(fullpath)
dfs = arcpy.mapping.ListDataFrames(mxd)
for df in dfs:
arcpy.AddMessage("DataFrame: " + df.name)
layers = arcpy.mapping.ListLayers(mxd, "", df)
for layer in layers:
if layer.isFeatureLayer:
lyr_source = layer.dataSource
lyr_name = layer.name.encode("utf8", "replace")
arcpy.AddMessage("Copying: {}".format(lyr_name))
print fullpath + lyr_source
wb.save('aaaaaaa.xlsx')
Thank you for your help. My next step is the openpyxl writing to excel.
Devin, have fun figuring out openpyyxl, sounds interesting. My choice sofar was writing to a csv file using open and write. Reading the question titel I think with this te discussion is complete.
I have tried write to csv also, but it seems that openpyxl is more versatile, e.g. write to a native xlsx .
I will see what works out for me and let you know.
I am going with csv instead, so I can share the script not worrying whether a person may or may not have openpyxl. Csv should suffice, but I am having a little trouble.
I have the following and can see the csv file in windows explorer processing/looping the files, but when I open the csv it has one file just repeated in several rows. You know what may be the cause?
with open('CSVLISTLAYERS.csv', 'wb') as outputcsv:
writer = csv.writer(outputcsv, dialect = 'excel')
for filename in (fullpath + lyr_source):
writer.writerow ([fullpath + lyr_source])
I found a script.
import arcpy, os
#Read input parameters from GP dialog
folderPath = arcpy.GetParameterAsText(0)
if folderPath=="":
folderPath = r"D:\TESTFOLDER"
#Loop through ech MXD file
for filename in os.listdir(folderPath):
fullpath = os.path.join(folderPath, filename)
if os.path.isfile(fullpath):
if filename.lower().endswith(".mxd"):
#open rapportfile for MXD
outFilename=fullpath[:fullpath.rfind(".")]+".csv"
mes= '\nMXD: %s' % (fullpath)
print mes
arcpy.AddMessage(mes)
rapportfile=open(outFilename,"w")
header='MXD;WORKSPACE;FEATURECLASS'
rapportfile.write(header+'\n')
mxd = arcpy.mapping.MapDocument(fullpath)
for df in arcpy.mapping.ListDataFrames(mxd):
layerList = arcpy.mapping.ListLayers(mxd, "", df)
mes='MXD %s bevat %s layers' % (filename, len(layerList))
arcpy.AddMessage(mes)
print mes
for lyr in layerList:
if lyr.supports("dataSource"):
workspace=lyr.workspacePath
fc=lyr.datasetName
print 'WorkspacePath: %s' % workspace
print 'FeatureClass: %s' % fc
reg='%s;%s;%s' % (filename,workspace,fc)
#arcpy.AddMessage(reg)
rapportfile.write(reg+'\n')
mes='Papportbestand: %s\n' % (outFilename)
print mes
arcpy.AddMessage(mes)
rapportfile.close()
del mxd
I am still working on trying to get the csv to write. You know about readlines and writelines? I just leaned of these, yet I haven't noticed anyone mentioning this option, ever.
the csv module is well documented 13.1. csv — CSV File Reading and Writing — Python 2.7.11 documentation and there are thousands of examples online
I have looked at many regarding csv writer, yet I am not successful yet.
This is part of my Python addin for data inventory and “broken-link” repair. tool box, but I'll include the first script here. It inventories and lists the fgdb to out put csv, and it also coverts it to an .xsl (not .xlsx). Maybe you can pick out what you need from this.
EDIT: bTW replace all the myMsgs with print or arcpy add message .
'''
---------------------------------------------------------------------------
Tool: FCInventoryReport
Toolbox: CheckAndFixLinks.tbx
Script: 2_InventoryFCs.py
Purpose:
This script will walk thru all the feature classes within a folder
and create a text report, comma-delimted and an Excel .xls file.
Include shapes, coverages, rasters, tables, connections, and FGDB
Column names: FType FCname FullPath
-------------------------------------------------------------------------------
Author: Rebecca Strauch - ADFG-DWC-GIS
Created on: 4/10/2013
last modification: August 10, 2015
Description: To create list of the features classes within a folder, including
coverages (pts, poly, arc, anno), shapes, grids and FGDB data. Outputs list
to a text report file (not much formatting) in the folder being scanned named
FCInventoryYYYYMMDD_HHMM.txt
with the date and time as part of the name. This should always create
a new file, unless you run it twice within same minute.
Must have write permissions on the output folder in question.
Known issue (with built-in workaround): for some reason some, but not
all (ArcInfo) grids want to duplicate the folder name before the
describe. I'm now checking to make sure it exists, if not, I am removing
the duplicate portion, and letting it run. Seems to work.
------------------------------------------------------------------------------
Arguments:
[0] theWorkspace: Folder/directory to search (walk thru, includes subfolders)
[1] outFile: output base filename, default GDBList, script appends YYYYMMDD_HHMM
Updates:
---------------------------------------------------------------------------
'''
# Import modules
import arcpy
import os
from _miscUtils import *
from _gpdecorators import *
# catch_errors decorator must preceed a function using the @ notation.
@catch_errors
def main():
"""
Main function to create text file report of all Feature Classes in folder
"""
#setup environment
arcpy.env.overwriteOutput = True
# Script arguments...
""" If running as standalone, hardcode theWorkspace and outFile """
theWorkspace = arcpy.GetParameterAsText(0)
if not theWorkspace:
theWorkspace = r"C:\__Data1\_TalkeetnaBU" # r"D:\_dataTest"
outFile = arcpy.GetParameterAsText(1)
if not outFile:
outFile = "FCInventory"
# Create new output name name tagged with YYYYMMDD_HHMM
fileDateTime = curFileDateTime()
currentDate = curDate()
# Create new output name tagged with YYYYMMDD_HHMM
outfileTXT = os.path.join(theWorkspace, outFile) + fileDateTime + ".txt" #theWorkspace + "\FCInventory" + fileDateTime + ".txt"
outFileCSV = os.path.join(theWorkspace, outFile) + fileDateTime + ".csv" #theWorkspace + "\FCInventory" + fileDateTime + ".csv"
outFileXLS = os.path.join(theWorkspace, outFile) + fileDateTime + ".xls"
arcpy.AddMessage(theWorkspace + ", " + outfileTXT)
reportFile = open(outfileTXT, 'w')
csvFile = open(outFileCSV, 'w')
arcpy.AddMessage( "File {0} is open? {1}".format(outfileTXT, str(not reportFile.closed)))
arcpy.AddMessage( "File {0} is open? {1}".format(str(outFileCSV), str(not csvFile.closed)))
#arcpy.AddMessage( "File " + str(csvFile) + " is closed? " + str(csvFile.closed))
arcpy.AddMessage("Writing the report to: " + outfileTXT + " and " + outFileCSV)
outText = "List of all GIS data in " + theWorkspace + " on " + currentDate + '\n'
outText += " Includes coverages (pts, poly, arc, anno), shapes, and FGDB data." + '\n'
outText += "-----------------------------------------------------" + '\n'
reportFile.write(outText)
csvFile.write("FType, FCname, FullPath\n")
def inventory_data(workspace, datatypes):
for path, path_names, data_names in arcpy.da.Walk(
workspace, datatype=datatypes):
if "tic" in data_names:
data_names.remove('tic')
for data_name in data_names:
fcName = os.path.join(path, data_name)
#arcpy.AddMessage("Show for debug: " + fcName)
if not arcpy.Exists(fcName):
# workaround for raster folder name duplicating
fcName = os.path.dirname(fcName)
desc = arcpy.Describe(fcName)
#arcpy.AddMessage("debug, desc it to me: " + desc.dataType)
yield [path, data_name, desc.dataType] #, desc]
i = 0
for feature_class in inventory_data(theWorkspace, "FeatureClass"):
""" last modified data not working for gdb or FC in fgdb ..."""
#lastMod = time.strftime('%m/%d/%Y %H:%M', time.localtime(os.path.getmtime(feature_class[0])))
if i == 0:
#arcpy.AddMessage("{0} modified: {1}".format(feature_class[0], lastMod))
arcpy.AddMessage("{0}".format(feature_class[0]))
outText = ' ' + feature_class[0] + '\n'
reportFile.write(outText)
path0 = feature_class[0]
i =+ 1
elif not path0 == feature_class[0]:
#arcpy.AddMessage("{0} modified: {1}".format(feature_class[0], lastMod))
arcpy.AddMessage("{0}".format(feature_class[0]))
outText = ' ' + feature_class[0] + '\n'
reportFile.write(outText)
i = 0
if feature_class[2] == "ShapeFile":
shpfile = arcpy.os.path.join(feature_class[0], feature_class[1])
lastMod = time.strftime('%m/%d/%Y %H:%M', time.localtime(os.path.getmtime(shpfile)))
arcpy.AddMessage(" {0}: {1} modified: {2}".format(feature_class[2], feature_class[1], lastMod))
outText = (" {0}: {1} modified: {2}\n".format(feature_class[2], feature_class[1], lastMod))
else:
arcpy.AddMessage(" {0}: {1}".format(feature_class[2], feature_class[1]))
outText = (" {0}: {1}\n".format(feature_class[2], feature_class[1]))
reportFile.write(outText)
csvFile.write("{},{}, {}\n".format(feature_class[2], feature_class[1], feature_class[0]))
reportFile.close()
csvFile.close()
arcpy.AddMessage( "File {0} is closed? {1}".format(outfileTXT, str(reportFile.closed)))
arcpy.AddMessage( "File {0} is closed? {1}".format(outFileCSV, str(csvFile.closed)))
# Creates Excel .xls file from the .csv ....easier to edit (ver 1)
arcpy.TableToExcel_conversion(outFileCSV, outFileXLS)
arcpy.AddMessage('!!! Success !!! ')
# End main function
if __name__ == '__main__':
main()