3

This is for ArcGIS 10, Python 2.65.

I have code which captures the extent of dataframes within all mxd's in a directory. I also want it to add the dataframe name, scale and the name of the MXD it extracted the extent polygon from.

The current code that I have give the following errors.

P:\2011\Job_031_TownPlanning_SeriesProduction\Working\mxd\1 P:\2011\Job_031_TownPlanning_SeriesProduction\Working\mxd\1\temp_extents Created...Polygon_Extent_1 Irvinebank I

Up to here the code is fine.

Executing: AddField P:\2011\Job_031_TownPlanning_SeriesProduction\Working\mxd\1\temp_extents\Polygon_Extent_1.shp ExtentID TEXT # # # # NON_NULLABLE NON_REQUIRED # Start Time: Thu May 12 08:49:57 2011 Adding ExtentID to P:\2011\Job_031_TownPlanning_SeriesProduction\Working\mxd\1\temp_extents\Polygon_Extent_1.shp... Succeeded at Thu May 12 08:49:57 2011 (Elapsed Time: 0.00 seconds)

It creates the column but I want it to put in the x'th value from the array of dataframe names and the test print statement only produces either the full list or the x'th character in the list.

Filling in Traceback (most recent call last): File "P:\2011\Job_031_TownPlanning_SeriesProduction\Working\mxd\1\extent_creation4.py", line 64, in row.strField = str(x) File "C:\Program Files\ArcGIS\Desktop10.0\arcpy\arcpy\arcobjects_base.py", line 35, in setattr return setattr(self._arc_object, attr, ao) RuntimeError: ERROR 999999: Error executing function.

These are errors in writing to the row. I also want it to capture the MXD file name

The updated code is below.

    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
    path2 = path + r'\temp_extents'
    mxdList = glob.glob(path + "\*.mxd")
    print 'Working in ' + path
    os.mkdir(path2)
    env.workspace = path2
    x = 0
    y = 1
    z = 1
    while y < 7:
    print 'Processing ' + mxd
    for mxd in mxdList:
    mxd2 = mapping.MapDocument(mxd)
    try:
        dataframe = mapping.ListDataFrames(mxd2, "*")[x]
        frameExtent = dataframe.extent
        print frameExtent
        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)
        #Create Polygon Shapefile
        arcpy.CreateFeatureclass_management(path2, "Polygon_Extent" + "_" + str(z), "POLYGON")
        arcpy.CopyFeatures_management(polygon, "Polygon_Extent" + "_" + str(z))
        print 'Created...' "Polygon_Extent" + "_" + str(z)

     #Capture and Enter ExtentID, File Name and other info
        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[x] # should show the full entry at storage x but instead shows the character at x
         dfStore = path2 + "\Polygon_Extent" + "_" + str(z) + ".shp"
         arcpy.AddField_management(dfStore,'ExtentID','TEXT') #should only be done once per shp
         arcpy.AddField_management(dfStore,'FileRef','TEXT') #should only be done once per shp
         arcpy.AddField_management(dfStore,'Scale','SHORT') #should only be done once per shp

      #END - Capture and Enter ExtentID, File Name and other info       
        z = z + 1

    except IndexError:
        pass
x = x + 1
y = y + 1

  list = []

  lstFCs = arcpy.ListFeatureClasses("Polygon_Extent*")
  print 'Merging Polygon_Extents* to Extent.shp'

  for fc in lstFCs:
      list.append(fc)

  arcpy.Merge_management(list, "Extent")
  print 'Created Extent.shp and exiting'

In response to the answer by Nathan.

Yes extentID=name of Dataframe.

I am still having problems with writing to the shapefile. I thought

         rows = arcpy.InsertCursor(dfStore, mxd2)
         row = rows.newRow()
         print 'Filling in ', rows
         row.ExtentID = ExtentIDStore
         filepath = mxd2.filePath # Gets full path of MXD used in your dataframe loop
         filename = os.path.basename(filepath) # Extracts the file name and extension
         row.FileRef = filename 
         scale = el.scale
         row.Scale = scale

would work but the values aren't inputed into the shapefile. What am I not understanding here?

---- UPDATED ISSUE

The code is now creating the desired output (of file name, extent, scale etc) but it seems to be overwriting the row which holds the polygon attribute -rather than appending the scale, extent etc values into the appropriate columns in the row.

I've tried placing the code for this in different loops but it makes no difference.

Output

Reading 2 mxd files from Q:\Software\GIS\ESRI\ArcGIS10\CustomScripts\temp\Extents Processing Q:\Software\GIS\ESRI\ArcGIS10\CustomScripts\temp\Extents\10_TownPlanning_B&L_Overlay_Ver2b_Kuranda.mxd Created...Q:\Software\GIS\ESRI\ArcGIS10\CustomScripts\temp\Extents\t10\Polygon_Extent_1.shp desc = Name: Shape Type : True Scale
: False Number of fields: 1 Filled in Koah 10_TownPlanning_B&L_Overlay_Ver2b_Kuranda.mxd 40000.0 into Q:\Software\GIS\ESRI\ArcGIS10\CustomScripts\temp\Extents\t10\Polygon_Extent_1.shp desc = Name: Shape Type : True Scale
: False Number of fields: 1 Filled in Overview 10_TownPlanning_B&L_Overlay_Ver2b_Kuranda.mxd 750000.0 into Q:\Software\GIS\ESRI\ArcGIS10\CustomScripts\temp\Extents\t10\Polygon_Extent_1.shp desc = Name: Shape Type : True Scale
: False Number of fields: 1 Filled in Kuranda 10_TownPlanning_B&L_Overlay_Ver2b_Kuranda.mxd 40000.0 into Q:\Software\GIS\ESRI\ArcGIS10\CustomScripts\temp\Extents\t10\Polygon_Extent_1.shp Processing Q:\Software\GIS\ESRI\ArcGIS10\CustomScripts\temp\Extents\9_TownPlanning_B&L_Overlay_Ver2b_MtMalloy.mxd ... Merging Polygon_Extents* to Extent.shp Deleting identical entries Created Extent.shp and exiting

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
path2 = path + r'\t6'
mxdList = glob.glob(path + "\*.mxd")
count_Mapdocs = len(mxdList)
#env.workspace = path + '\extents' # Directory as files being processed

print 'Reading '+str(count_Mapdocs)+ ' mxd files from ' + path
os.mkdir(path2)
env.workspace = path2


x = 0
y = 1
z = 1

while y < 7:
    for mxd in mxdList:
        print 'Processing ' + mxd
        mxd2 = mapping.MapDocument(mxd)
        try:
            dataframe = mapping.ListDataFrames(mxd2, "*")[x]
            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)
            #Create Polygon Shapefile
            arcpy.CreateFeatureclass_management(path2, "Polygon_Extent" + "_" + str(z), "POLYGON")
            arcpy.CopyFeatures_management(polygon, "Polygon_Extent" + "_" + str(z))

            dfStore = path2 + "\Polygon_Extent" + "_" + str(z) + ".shp"
            print 'Created...' + dfStore
            arcpy.AddField_management(dfStore,'ExtentID','TEXT') #should only be done once per shp
            arcpy.AddField_management(dfStore,'FileRef','TEXT') #should only be done once per shp
            arcpy.AddField_management(dfStore,'Scale','FLOAT') #should only be done once per shp


#Capture and Enter ExtentID, File Name and other info
            for el in arcpy.mapping.ListLayoutElements(mxd2, "DATAFRAME_ELEMENT"):
             desc = arcpy.Describe(dfStore)
             print "desc =" + str(desc)
             indexList = arcpy.ListIndexes(dfStore)

            # Iterate through the list of indexes
            # This is just to check on whats going on.
             for index in indexList:
                # Print index properties
                #
                print "Name: " + index.name
                print "\tType            : " + str(index.isAscending)
                print "\tScale           : " + str (index.isUnique)
                print "\tNumber of fields: " + str(len(index.fields))
             rows = arcpy.InsertCursor(dfStore, desc)
             row = rows.newRow()
             ExtentIDStore = el.name
             row.ExtentID = ExtentIDStore
             filepath = mxd2.filePath # Gets full path of MXD used in your dataframe loop
             filename = os.path.basename(filepath) # Extracts the file name and extension
             row.FileRef = filename
             scale = el.scale
             row.Scale = float(scale)

                         # This is just to check on whats going on.
             print 'Filled in ', str(ExtentIDStore), str(filename), str(scale) + " into " + dfStore 

             rows.insertRow(row) # insert value into the row (should be the same row as 
            z = z + 1
        except IndexError:
            pass

    x = x + 1
    y = y + 1

list = []

lstFCs = arcpy.ListFeatureClasses("Polygon_Extent*")
print 'Merging Polygon_Extents* to Extent.shp'

for fc in lstFCs:
    list.append(fc)

arcpy.Merge_management(list, "Extent")
print 'Deleting identical entries'
arcpy.DeleteIdentical_management("Extent.shp", ["SHAPE"])
print 'Created Extent.shp and exiting'
6
  • 2
    Could you elaborate on what you are doing?
    – user681
    Commented May 11, 2011 at 3:19
  • 1
    It is not clear if you want to use a datafame extent to insert a value into a field attribute. or possibly insert a dynamically generated shape file into a dataframe. I would say either way you need to make it clearer what you are looking for.
    – Brad Nesom
    Commented May 11, 2011 at 4:20
  • sorry... I am capturing the extents of multiple mxd's into a single shape file (working) and now I want to write the dataframe ID into the shape file. It should also add in the name of the mxd and the scale. For some reason the following ... 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[x] # should show the full entry at storage x but instead shows the character at x ... Thanks for your help.
    – GeorgeC
    Commented May 11, 2011 at 7:09
  • 2
    @geoge - it is ok to edit your question and add, clarify, or post images to help. The formatting is much easier to read in the question as opposed to the comments.
    – Brad Nesom
    Commented May 11, 2011 at 13:11
  • 1
    Thanks Dan and Brad. I have updated the post and included the whole code. I really appreciate your help. Cheers,
    – GeorgeC
    Commented May 12, 2011 at 0:28

1 Answer 1

1

I'm a bit lost here, so my answer may be off base. When you say you want the ExtentID, that appears to be the name of the Dataframe you're exporting the extent of. If this is the case (which is what your code is doing to my best guess), you don't need the [x] index when printing it. :

 for el in arcpy.mapping.ListLayoutElements(mxd2, "DATAFRAME_ELEMENT"):
     ExtentIDStore = str(el.name)
     #print x, y, z <--- You don't need to print x y and z. They are unrelated at this point.
     print ExtentIDStore #used to see which item to add to the shape file

     print ExtentIDStore[x] # <- This will just print an indexed character in the string

By the time you reach the loop above, your code is only concerned with the Dataframe Element in question, so there is no need to do any indexing for storage. ExtendIDStore should be what you add to the shapefile row.

Your error which results at this line:

row.strField = str(x)

Is probably because you are not referencing a field that exists. What comes after the row reference is the name of the Field. In this case, it should be:

row.ExtentID = ExtentIDStore

File name you can get via the filePath property of the MapDocument class and the os.path.basename method, i.e.:

filepath = mxd2.filePath # Gets full path of MXD used in your dataframe loop
filename = os.path.basename(filepath) # Extracts the file name and extension
row.FileRef = filename

If you don't want the extension, use filename.strip(".mxd") to remove it.

Scale would be:

scale = el.scale # Scale of the dataframe referenced in the loop
row.Scale = scale

And that should fill in the rows you're looking for.


For the new problem, I think you are misusing the insert cursor. The second argument should be a spatial reference, which cannot be gleaned via an MXD. I would recommend creating the cursor with only one argument (the output file or dfStore). You also forgot the last (and most important) line:

rows.insertRow(row)

Without that your data never gets put into the table. Put that down at the end of the row loop so that the data is actually inserted after all the variables are set.


For more information about accessing Dataframe, layer, and map properties (scale, name, current position), check out the mapping module. The scale property of the Dataframe class can be seen on the classes page of the same name.

6
  • Thanks N. Please see my edited Q above. I couldn't figure out how to include code etc in the comments.
    – GeorgeC
    Commented Jun 7, 2011 at 4:02
  • Editing your question is the right option to add code and update it as your needs change. Updated my answer for you. Give it a shot!
    – Nathanus
    Commented Jun 7, 2011 at 15:22
  • Thanks. This works great. The only issue is with scale - "el.scale" is el meant to be the current dataframe/extent? and scale a value extracted automatically by python from it? What document lists all the values that Python can extract from a mxd...? Sorry I am learning python without any formal course...
    – GeorgeC
    Commented Jun 9, 2011 at 3:46
  • Added a post script for you with some references.
    – Nathanus
    Commented Jun 9, 2011 at 12:26
  • What am I doing wrong? the script seems to be adding the extent, scale etc into a new row and overwriting the polygon attributes of the row. I've updated the question with the new code and output. Thanks for your help so far...
    – GeorgeC
    Commented Jun 9, 2011 at 23:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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