[GIS] Inserting DATAFRAME_ELEMENT value into dynamically generated shapefile containing its extent

arcgis-10.0arcpyerror-999999

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'

Best Answer

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.

Related Question