Select to view content in your preferred language

Automating capture of Extent from multiple mxds with multiple dataframes

4801
35
04-19-2011 03:14 PM
George_ChandeepCorea
Occasional Contributor
Hi,

I want to create a single shape file from multiple mxd's that have multiple frame sets with different extents in them. I have found/started a script to do this (attached) but can't figure out how to write the captured X&Y Max/Min into the shape file that is created for this. See output below. I also want it to write the scale and title of the frame as well as the file name of the mxd.

Would appreciate your help in completing this script.

Thanks,

>>> import arcpy, os, glob
... #path = 'c:\\temp\\george\\'
... path = 'P:\\2011\\Job_031_TownPlanning_SeriesProduction\\Working\\mxd\\1'
... os.chdir(path)
... mxds_List = glob.glob('*.mxd')
... count_Mapdocs = len(mxds_List)
... print 'Processing ' + str(count_Mapdocs) + 'map documents...'
... #Create Polygon Shapefile
... arcpy.CreateFeatureclass_management(path, 'extents.shp', "POLYGON")
... #Start Loop
... for mxd in mxds_List:
...     mapDoc = arcpy.mapping.MapDocument(mxd)
...     dataframe = arcpy.mapping.ListDataFrames(mapDoc,'*')[0]
...     frameExtent = dataframe.extent
...    
...     #Frame Scale
...     frameScale = dataframe.scale
...     #Frame Extent
...     ExtentXMax = frameExtent.XMax
...     ExtentXMin  = frameExtent.XMin
...     ExtentYXax  = frameExtent.YMax
...     ExtentYMin  = frameExtent.YMin
...    
...     point_object = mxd.shp
...     #Write in table scale
...     #Write in table

Processing 14map documents...

Runtime error <type 'exceptions.AttributeError'>: 'str' object has no attribute 'shp'
Tags (2)
0 Kudos
35 Replies
George_ChandeepCorea
Occasional Contributor
Nicholas,

Thanks for sending the code. When I try it, I get the following even though there are ver 10 MXD's in the directory. Please see the attachment (2.rar) to my last post. Following change was made to the code...

#scriptPath = sys.path[0]
scriptPath = r'P:\2011\Job_031_TownPlanning_SeriesProduction\Working\mxd\1'


>>>
Executing: mapindex
Start Time: Tue May 10 11:59:56 2011
Running script mapindex...
Script path is P:\2011\Job_031_TownPlanning_SeriesProduction\Working\mxd\1
No ArcMap Documents were found in this folder. Please try another folder.
Completed script mapindex...
Failed to execute (mapindex).
Failed at Tue May 10 11:59:56 2011 (Elapsed Time: 0.00 seconds)
>>>


best,
0 Kudos
deleted-user-1T_bOHag6M8d
Deactivated User
Nicholas,

Thanks for sending the code. When I try it, I get the following even though there are ver 10 MXD's in the directory. Please see the attachment (2.rar) to my last post. Following change was made to the code...

#scriptPath = sys.path[0]
scriptPath = r'P:\2011\Job_031_TownPlanning_SeriesProduction\Working\mxd\1'


>>>
Executing: mapindex
Start Time: Tue May 10 11:59:56 2011
Running script mapindex...
Script path is P:\2011\Job_031_TownPlanning_SeriesProduction\Working\mxd\1
No ArcMap Documents were found in this folder. Please try another folder.
Completed script mapindex...
Failed to execute (mapindex).
Failed at Tue May 10 11:59:56 2011 (Elapsed Time: 0.00 seconds)
>>>


best,


Chandeep,

My script looks for MXDs in the arcpy.env.workspace setting which is set by the wp variable, not the scriptPath.

If you keep my folder structure the same, you should need to make changes to the scriptPath. The only change you should need is to the wp and spatialRef variables. My script uses a custom ArcGIS tool in the root folder which allows you to select these variables.

Can you try running the MapIndexTool in the toolbox in either ArcCatalog or ArcMap and see if it works for you. A shapefile will be created in the same folder as the MXDs.
0 Kudos
JakeSkinner
Esri Esteemed Contributor
Thanks for sending your code and MXDs.  I didn't take into consideration that you had multiple dataframes within your MXDs.  I've updated the code to work with this.  There were a few small syntax errors within the code you sent. 

For example:

env.workspace = path + 'extents.gdb'


There is a '\' missing.  Should be:

env.workspace = path + '\extents.gdb'


Another error:

for mxd in mxdList:
    mxd = mapping.MapDocument(mxd)
    print mxd # Printing status for error checking
    dataframe = mapping.ListDataFrames(mxd2, "*")[0]


Need to change the second 'mxd' to 'mxd2':

for mxd in mxdList:
    mxd2 = mapping.MapDocument(mxd)
    print mxd # Printing status for error checking
    dataframe = mapping.ListDataFrames(mxd2, "*")[0]


I also removed the 'Tempfile' from the code.  This isn't really needed, but the code may still work with it added (did not test though).  Below is the updated code.  This code will also iterate through all dataframes in each MXD:

import arcpy, glob, os
from arcpy import env
from arcpy import mapping
env.overwriteOutput = True

path = os.getcwd() # Script in same directory as files being processed
mxdList = glob.glob(path + "\*.mxd")
env.workspace = path + '\extents.gdb' # Directory as files being processed
print env.workspace

x = 0
y = 1
z = 1

while y < 7:
    for mxd in mxdList:
        mxd2 = mapping.MapDocument(mxd)
        try:
            dataframe = mapping.ListDataFrames(mxd2, "*")
            frameExtent = dataframe.extent
            XMAX = frameExtent.XMax
            XMIN = frameExtent.XMin
            YMAX = frameExtent.YMax
            YMIN = frameExtent.YMin
            pnt1 = arcpy.Point(XMIN, YMIN)
            pnt2 = arcpy.Point(XMIN, YMAX)
            pnt3 = arcpy.Point(XMAX, YMAX)
            pnt4 = arcpy.Point(XMAX, YMIN)
            array = arcpy.Array()
            array.add(pnt1)
            array.add(pnt2)
            array.add(pnt3)
            array.add(pnt4)
            array.add(pnt1)
            polygon = arcpy.Polygon(array)
            arcpy.CopyFeatures_management(polygon, "Polygon_Extent" + "_" + str(z))
            z = z + 1
        except IndexError:
            pass
    x = x + 1
    y = y + 1

list = []

lstFCs = arcpy.ListFeatureClasses("Polygon_Extent*")
for fc in lstFCs:
    list.append(fc)

arcpy.Merge_management(list, "Extent")

for item in list:
    arcpy.Delete_management(item)


For "while > 7:", the number can be any value that is larger than the max amount of dataframes in any individual MXD.  For example, if you had an MXD that has 10 dataframes you should increase this number to 10 (dataframe indexing begins at 0).
0 Kudos
George_ChandeepCorea
Occasional Contributor
Jake, Thanks again.

Without any changes to the script I get

>>>
P:\2011\Job_031_TownPlanning_SeriesProduction\Working\mxd\1\extents.gdb
Traceback (most recent call last):
  File "P:\2011\Job_031_TownPlanning_SeriesProduction\Working\mxd\1\extent_creation3.py", line 36, in <module>
    arcpy.CopyFeatures_management(polygon, "Polygon_Extent" + "_" + str(z) + ".shp")
  File "C:\Program Files\ArcGIS\Desktop10.0\arcpy\arcpy\management.py", line 1943, in CopyFeatures
    raise e
ExecuteError: ERROR 000210: Cannot create output Polygon_Extent_1.shp
Failed to execute (CopyFeatures).
>>>

Did your code work on your machine?

It seems like this is a rw error so I tried to create the shp file as below and it created the file but you still get the same error as above. It also could be an error in "C:\Program Files\ArcGIS\Desktop10.0\arcpy\arcpy\management.py", line 1943, in CopyFeatures? but I am on a default installation.

            polygon = arcpy.Polygon(array)
            #Create Polygon Shapefile
            arcpy.CreateFeatureclass_management(path, "Polygon_Extent" + "_" + str(z), "POLYGON")
            #
            arcpy.CopyFeatures_management(polygon, "Polygon_Extent" + "_" + str(z))
            z = z + 1


Also I wanted to check - are the following correct?

1. while y < 7: === this loop creates a shp file with the extents of each dataframe? I guess I can use the same loop to also add in the scale and name of the dataframe into the shp file?
2. for fc in lstFCs: ==== take all the "polygon_extent_*.shp" files and merge them into extents.shp?
3. for item in list: ==== delete the "polygon_extent_*.shp"?
0 Kudos
George_ChandeepCorea
Occasional Contributor
Jake,

I got the script to work. We were trying to write to extent.gdb but didn't create it, also needed to create the poly*.shp files before writing to them. I will post the full code tomorrow as it's on my office computer.

To add the ExtentID I added the following code but it doesn't extract the full name properly.

for el in arcpy.mapping.ListLayoutElements(mxd2, "DATAFRAME_ELEMENT"):
 ExtentIDStore = str(el.name)
 print ExtentIDStore #used to see which item to add to the shape file 
 print ExtentIDStore # should show the full entry at storage x but instead shows the character at x


Also I wanted to check - are the following correct?

1. while y < 7: === this loop creates a shp file with the extents of each dataframe? I guess I can use the same loop to also add in the scale and name of the dataframe into the shp file?
2. for fc in lstFCs: ==== take all the "polygon_extent_*.shp" files and merge them into extents.shp?
3. for item in list: ==== delete the "polygon_extent_*.shp"?
0 Kudos
JakeSkinner
Esri Esteemed Contributor
Jake,

1. while y < 7: === this loop creates a shp file with the extents of each dataframe? I guess I can use the same loop to also add in the scale and name of the dataframe into the shp file?
2. for fc in lstFCs: ==== take all the "polygon_extent_*.shp" files and merge them into extents.shp?
3. for item in list: ==== delete the "polygon_extent_*.shp"?


The script is intended to create feature classes within the Extents.gdb, which you will need to create before running the script.  This is why you were receiving errors referencing shapefiles.  I believe since the file geodatabase did not exist, the script attempted to create a shapefile.  The 'env.workspace' is set to the Extents.gdb, so all output should be written here.

1.  The while loop with iterate through each mxd starting with the first dataframe, where x = 0.  X will then increase by 1 and iterate through each mxd with the next dataframe[1].  If the dataframe does not exist, for example the mxd does not contain dataframe[4], the script will execute the 'except' and pass the index error.  Yes, you could use the same loop to add the scale and dataframe name to the feature class, but this will take some more coding.

2.  This will take all 'polygon_extent' feature classes and merge them into one feature class.

3.  After the 'polygon_extent' feature classes are merged into one, it will delete the individual 'polygon_extent' feature classes.

Hope this helps!
0 Kudos
George_ChandeepCorea
Occasional Contributor
Thanks Jason,

I have added to the code to capture the extent ID (it can fill in filename as 'mxd' and not sure how to capture scale) but it is giving errors in identifying the x'th entry in to the list -it prints just the x'th character. Also it's not clear where to put a print statment to give feedback that the program is working on the 2,3,4th etc mxd file.

>>>
Reading mxd files from P:\2011\Job_031_TownPlanning_SeriesProduction\Working\mxd\1
Working in P:\2011\Job_031_TownPlanning_SeriesProduction\Working\mxd\1\temp_extents
Processing P:\2011\Job_031_TownPlanning_SeriesProduction\Working\mxd\1\TownPlanning_Bushfire_Overlay_Ver2-Herberton.mxd
Created...Polygon_Extent_1
Irvinebank
I
Watsonville
W
Overview
O
Herberton
H


Here ExtentIDStore prints the whole value but ExtentIDStore only prints the x'th character rather than the value in the x'th position.

I also notice that it loops first through the mxd's creating extent 1, then loops through creating extent 2 etc. I was initially thinking that it opened the first mxd, cycled through and created all the extent polygons and then opened the next mxd and created the extents.

Traceback (most recent call last):
  File "P:\2011\Job_031_TownPlanning_SeriesProduction\Working\mxd\1\extent_creation4.py", line 78, in <module>
    rows = arcpy.InsertCursor(FileRef)
  File "C:\Program Files\ArcGIS\Desktop10.0\arcpy\arcpy\__init__.py", line 837, in InsertCursor
    return gp.insertCursor(*args)
  File "C:\Program Files\ArcGIS\Desktop10.0\arcpy\arcpy\geoprocessing\_base.py", line 367, in insertCursor
    self._gp.InsertCursor(*gp_fixargs(args)))
RuntimeError: ERROR 999999: Error executing function.
>>>



I'm not sure what to do?
0 Kudos
JakeSkinner
Esri Esteemed Contributor

I have added to the code to capture the extent ID (it can fill in filename as 'mxd' and not sure how to capture scale) but it is giving errors in identifying the x'th entry in to the list -it prints just the x'th character. Also it's not clear where to put a print statment to give feedback that the program is working on the 2,3,4th etc mxd file.


You will need to append the extent ID to a list.  Ex:

for el in arcpy.mapping.ListLayoutElements(mxd2, "DATAFRAME_ELEMENT"):
        ExtentIDStore = str(el.name)
        list2.append(ExtentIDStore)


Then you can use print statement for the list:

print list2[0]




I also notice that it loops first through the mxd's creating extent 1, then loops through creating extent 2 etc. I was initially thinking that it opened the first mxd, cycled through and created all the extent polygons and then opened the next mxd and created the extents.


You can code it to do it this way, but the end result will be the same.


Also it's not clear where to put a print statement to give feedback that the program is working on the 2,3,4th etc mxd file.


You can execute a print statement at the beginning of the first 'for' loop:
for mxd in mxdList:
    mxd2 = mapping.MapDocument(mxd) 
    print mxd


However, the same MXD name will be printed multiple times since the code loops through each MXD multiple times.
0 Kudos
George_ChandeepCorea
Occasional Contributor
Hi Jake,

Then you can use print statement for the list:

print list2[0]


I tried but I get an error --

Traceback (most recent call last):
  File "P:\2011\Job_031_TownPlanning_SeriesProduction\Working\mxd\1\Extent_Generation.py", line 58, in <module>
    list2.append = ExtentIDStore
AttributeError: 'str' object has no attribute 'append'


I tried to figure out why from the esri/python help system but can't understand the reason for it.

----

I am also not able to get the write function to work and do you know if I can capture the scale.

On the write functions I get the following errors...

  File "P:\2011\Job_031_TownPlanning_SeriesProduction\Working\mxd\1\Extent_Generation.py", line 81, in <module>
    rows = arcpy.InsertCursor(FileRef)
NameError: name 'FileRef' is not defined



It's not very important but I am trying to delete the temp directory at the start of the script but the code I tried to use doesn't seem to work as part of the script, although it's fine when run in the arcmap python window.

Thanks again for all your support and help on this...
0 Kudos
LT
by
Regular Contributor
Hi folks,

I was trying to make a polygon based on the extent of a layer and so I used code very much like what's on this thread

#Find extent

#Create poly

#Copy Feature

But it gives me a polygon with no area (and evidence of existence on the map). 

It's weird that none you seem to mention this problem, so I'm wondering if a new bug has arrived with one of the service packs?

Here's some sample code that runs 'successfully' but creates a polygon of area zero.  I'd attach a pic of my output polygon, but I think you can picture it in your heads.  Imagine some empty white space!
(I can probably just use a min. bounding box tool call instead, but I'd still like to know if the polygon creation is broken.)

Thanks.

import sys, arcpy

dataDir = "C:/Temp"
arcpy.overwriteOutput = True
arcpy.env.workspace = dataDir

#Get extent
fc = "input.shp"
desc = arcpy.Describe(fc)
extent = desc.Extent

#Create polygon
pts = [ [extent.XMin, extent.YMin],
[extent.XMin, extent.YMax],
[extent.XMax, extent.YMax],
[extent.XMax, extent.YMin] ]
point = arcpy.Point()
array = arcpy.Array()

for pt in pts:
    point.x = pt[0]
    point.y = pt[1]
    array.add(point)
array.add(array.getObject(0))

SR = desc.spatialReference
poly = arcpy.Polygon(array,SR)

#Copy features
arcpy.CopyFeatures_management(poly, "Polygon_Extent")
0 Kudos