Create MXD for each FC row

611
6
05-23-2013 05:20 PM
AlexGole1
New Contributor II
Hi all,
I have FC with 125 rows, and I would like to make a separate MXD for each single attribute I have got . In this case I will be using the FID for my loop. My scripts is not working as I wish. Do anyone have an idea how to automate this process? Thank you

Attach is my script:


import arcpy, os
from arcpy import env
#Overwrite features
arcpy.env.overwriteOutput = True

shape = r"K:\Working\Alex_Gole\cult.shp"
output = r"K:\Working\Alex_Gole\test"
layer = r"K:\Working\Alex_Gole\letter_lyr_new"
rows = arcpy.SearchCursor(shape, "", "", "FID", "FID")
mxd = arcpy.mapping.MapDocument(r"K:\Working\Alex_Gole\Try.mxd")
df = arcpy.mapping.ListDataFrames(mxd, "Layers")[0]
inset = arcpy.mapping.ListDataFrames(mxd, "New Data Frame")[0]

#For each work order:
for row in rows:
    # Create a clause to select only the current record
    whereclause = '"FID" = ' + str(row.FID)
    # Create a feature layer from the current row only
    arcpy.MakeFeatureLayer_management(shape, layer, whereclause)
    #Create feature class for each point
    arcpy.CopyFeatures_management(layer, r"K:\Working\Alex_Gole\test\try.shp" + str(row.FID))
    newMxd = "Fig1_" + row.Name + ".mxd"
    pathNewMxd = r'K:\Working\Alex_Gole\test\\' + newMxd
    if os.path.exists(pathNewMxd):
        pass
    else:   
        #copy template and name file "Fig1_Task_WO_Name_NuPoles"
        mxd.saveACopy(r"K:\Working\Alex_Gole\test\\"
                        + newMxd)
       
        print "Saving " + newMxd
   
print "All done."

del mxd
Tags (2)
0 Kudos
6 Replies
markdenil
Occasional Contributor III
To start: read the post pinned at the top of the list about how to post readable code.

Don't try to do stuff inside your cursor loop.
Use the cursor to create a list of FIDs, close the cursor, and then itterate the list.
If you want to save other field values too, use another list and step theough them in paralel
using the list index
theList = ['a', 'b', 'c', 'd']
otherList = [1, 2, 3, 4]
listLength = len(theList)
for x in range(0, listLength):
    print str(theList), str(otherList)

or using a dictionary keyed to the FID, and itterate the dictionary keys list.

Try setting the definition query on the layer(s) you already have in the data frame (UpdateLayer)
instead of making new layers.
In any event, although you (try to) make layers in your script,
I don't see where you add them to the mxd, symbolize them, or remove them when you are done with them.
0 Kudos
KimOllivier
Occasional Contributor III
Why would you want 125 MXD files in the first place?? Surely the point of Python scripting is that you manipulate one MXD to avoid the proliferation of MXD files. Out of curiosity I have just done a count on my system and I only have 222 MXD files after 10 years of ArcGIS processing.

The mapping module helps a lot with reducing the number of MXDs required, but you can also use templates, layer files, styles to reduce the number.
0 Kudos
TimDine
Occasional Contributor II
The only reason I could picture that many mxds would be something that could be solved with Data Driven Pages.  I use a python script to change queries on an index layer and generate maps based on that.  It could be worth some investigation to see if it solves what you're really trying to accomplish.
0 Kudos
RhettZufelt
MVP Frequent Contributor
Not sure why you would want a separate mxd, but do you also want to duplicate the data for each one as well?

Why not just put a definition query on the mxd to match the FID that you want, zoom to the displayed features, then save as a new mxd.  Then, change the definition query to the next one, zoom to extent, then save as new mxd.  This will give you a map document  for each of your 125 features, but will utilize the one, already existing data set without having to make a copy.

something like this should do it:  BTW row.name should be row.getValue('Name') - part of why yours wasn't working.

import arcpy, os
from arcpy import env
#Overwrite features
arcpy.env.overwriteOutput = True

shape = r"K:\Working\Alex_Gole\cult.shp"
output = r"K:\Working\Alex_Gole\test"
layer = r"K:\Working\Alex_Gole\letter_lyr_new"
mxd = arcpy.mapping.MapDocument(r"K:\Working\Alex_Gole\Try.mxd")
df = arcpy.mapping.ListDataFrames(mxd, "Layers")[0]
inset = arcpy.mapping.ListDataFrames(mxd, "New Data Frame")[0]


lyr1 = arcpy.mapping.ListLayers(mxd, "cult", df)[0]  # pick the layer you want to "extract" data from


#For each work order:
rows = arcpy.SearchCursor(lyr1, "", "", "FID", "FID")
for row in rows:
   name = str(row.getValue('Name'))
   sqlExp = '"FID" = ' + str(row.getValue('FID'))    # Create a clause to select only the current record
   lyr1.definitionQuery = sqlExp
   df.extent = lyr1.getSelectedExtent(True)


newMxd = "Fig1_" + name
mxd.saveACopy(r"K:\Working\Alex_Gole\test\\" + newMxd + ".mxd")

print "Saving ", newMxd + ".mxd"

print "All done."

del mxd 



I have a script that is similar, but instead of saving as a new mxd each time (especially since I have over 8000 records), I just

arcpy.mapping.ExportToJPEG(mxd, outfile, resolution=266)

and export to a jpeg file, and move on to the next FID since this is the final output desired anyway.
R_
0 Kudos
AlexGole1
New Contributor II
First of all thank you, your script helped me a lot figure out how to iterate a query.
Now, I know a little bit more about the project.  The goal is actually to query through a species_ID and export MXD to PDF.The problem is that Species_ID holds multiple values. For instance query: species_ID = 1, 150 records will be returned. It not a row by row query unfortunately. I am also trying to update the title and legend label name for each query. I have used ArcGIS 10.1 to access a list of species_ID. However, I am not familiar at all with this new search cursor, I would not know .
Thank you,
Alex 


#Creates draft MXDs for each 1 pole work order.
import arcpy, os
from arcpy import env
#enable overwrite 
arcpy.env.overwriteOutput = True

###
###Cycles through 1 pole work orders and creates MXDs
###
shape = r"K:\Working\Alex_Gole\cult.shp"
output = r"K:\Working\Alex_Gole\test"
finalPdf = arcpy.mapping.PDFDocumentCreate(os.path.join(output, "All.pdf"))   #ADJUST FILE PATH METHOD
field = "voila"
MyList = [3, 4, 5, 6, 7]
for values in MyList:
    whereclause = '"voila"' "= " + str(values)
rows = arcpy.SearchCursor(shape, "", "", "voila; Letter")
mxd = arcpy.mapping.MapDocument(r"K:\Working\Alex_Gole\Try_new.mxd")
dfs = arcpy.mapping.ListDataFrames(mxd)[0]
titleElem = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT","Figure name")[0]
labelElem = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT","Label")[0]
#change definition querry of poles to match work order
for row in rows:
    # Create a clause to select only the current record
    titleElem.text = str(row.voila)
    labelElem.text = str(row.Letter)
    for df in dfs:
        for lyr in arcpy.mapping.ListLayers(mxd, "voila"):
            #set the definition query of the poles layer
            lyr.definitionQuery = whereclause
    #Export each theme to a temporary PDF and append to the final PDFprint "export to pdf"
    tmpPdf = os.path.join(output, str(row.voila) + ".pdf")  #ADJUST FILE PATH METHOD
    arcpy.mapping.ExportToPDF(mxd, tmpPdf, resolution=240)
    finalPdf.appendPages(tmpPdf)
    
print "All done."

del mxd
0 Kudos
RhettZufelt
MVP Frequent Contributor
Alex,

Could use a little more clarification here.

So, first of all, are you saying that you want one pdf exported for each FC in your layer or one for each species_ID?
IOW, for species_ID = 1, it returns 150 records. Do you want one pdf created that shows all 150 features in the extent, or do you actually want 150 pdf documents, one for each of the species_ID=1 features?
(based on last repsonse, I assume you really don't need separate mxd's, just as long as you have separate PDF's ?)

Also, need to clarify if you are searching/def query on the voila layer or the poles layer as this code applies it to the cult.shp layer???
need to iterate through the layer you are actually applying query to. As is, will set the definitionQuery on a layer "poles" in DF "Layers" to the value of "voila" from the cult.shp layer attribute table. I normally SearchCursor the same FC I'm applying the definition query to, that way there is always a "match".


import arcpy, os

shape = r"K:\Working\Alex_Gole\cult.shp"
output = r"K:\Working\Alex_Gole\test\"
output = "in_memory\"      ## to save temp pdf "in memory" to save filespace and speed.  Not sure if this will work for the pdf tool.  If not, delete unless you need individual PDF's after appending.
finalPdf = arcpy.mapping.PDFDocumentCreate(os.path.join(output, "All.pdf"))   #ADJUST FILE PATH METHOD
mxd = arcpy.mapping.MapDocument(r"K:\Working\Alex_Gole\Try_new.mxd")


#MyList = [3, 4, 5, 6, 7]
#for values in MyList:
#    whereclause = '"voila"' "= " + str(values)                              ###  this is actually setting your whereclause = "voila" = 7 as it is the last in your list, and there is nothing else to "do" here...

dfs = arcpy.mapping.ListDataFrames(mxd, "Layers")[0]                                              ## Have to adjust if you need the query, etc. on more than one dataframe
titleElem = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT","Figure name")[0]  ##  Assuming you have created a text element in mxd with Element Name = "Figure name"
labelElem = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT","Label")[0]            ##  Assuming you have created a text element in mxd with Element Name = "Label"
lyr1 = arcpy.mapping.ListLayers(mxd, "poles", dfs)[0]                          ## Have to adjust if you need the query, etc. on more than one dataframe


sCur = arcpy.SearchCursor(shape)

for row in sCur:
    voila_var = str(row.getValue(voila)) 
    letter_var = str(row.getValue(Letter)) 
    fid_var = row.getValue(FID)
    whereclause = '"voila" = \'' + voila_var + "'                            ## creates PDF for each macthing FC
    #whereclause = '"FID" = ' + str(fid_var)                                   ## comment out other whereclause and use this one to create PDF for EACH FC, regardless of voila value.
    titleElem.text = voila_var    
    labelElem.text = letter_var
    lyr1.definitionQuery = whereclause                                       ## This actually puts defquery on the poles layer using the cult.shp values??
    mxd.save()                               ## need to save chages to mxd before you export to PDF or changes won't be represeted.
 
    #Export each theme to a temporary PDF and append to the final PDFprint "export to pdf"
    tmpPdf = os.path.join(output, voila_var + ".pdf")  #ADJUST FILE PATH METHOD
    arcpy.mapping.ExportToPDF(mxd, tmpPdf, resolution=240)
    finalPdf.appendPages(tmpPdf)
    
print "All done."

del mxd


If this workflow doesn't get you on the right track, let us know the other specifics.
Have not tested this specifically, but is right our of one of my working scripts, so the basic structure should work. Might have to adjust variable names, syntax, etc.,

R_
0 Kudos