Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

Do labels needed to be coded into an arcpy script in order to be visible on an arcpy .pdf output? In ArcGIS the labels are visible for various features, but when I use the arcpy script (either in IDLE or in ArcGIS directly) only certain labels appear. I've checked the Label manager and verified the expressions (i.e. making sure they're visible at a large scale (1:1000) but everything looks ok). Interestingly, it's only the labels for the features that are run through the script that don't appear. Any thoughts would be much appreciated

Edit: I've checked to make sure the layers are visiblelabel manager view

Two things that are additionally weird: 1) every time I run the code I get a slightly different result, i.e. some with label, some without, and 2) although the code is producing the right number of individual .pdfs, they are all for the same record, i.e. there are 17 .pdfs produced for 17 records, but each one is the same (I know this last part is likely considered a second question, but something tells me they're related).

Here's the full code:

mxd = arcpy.mapping.MapDocument("C:\\temp\\Graffiti_DM3.mxd")
df = arcpy.mapping.ListDataFrames(mxd, "*")[0]
graffitilyr=arcpy.mapping.ListLayers(mxd, "*", df)[0]

newquery = '"Incident_Z" =' + "'10003'"
graffitilyr.definitionQuery=newquery
features = arcpy.SearchCursor(graffitilyr)
count = 1

print "let's get started"
for feature in features:
        df.rotation = "0"
        arcpy.SelectLayerByAttribute_management(graffitilyr, "NEW_SELECTION", "FID=" + str(count))
        #df.extent = graffitilyr.getSelectedExtent(True)
        df.zoomToSelectedFeatures()
        df.scale = df.scale * .004
        arcpy.RefreshActiveView()
        df.panToExtent(graffitilyr.getSelectedExtent())
        #df.scale = "1000"
        outpdf="C:\\temp\\" + str(count) + ".pdf"
        arcpy.mapping.ExportToPDF(mxd,outpdf)
        count = count+1
share|improve this question
2  
Have you done a simple check to make sure that the labels are set to be visible on the layer itself? This is different from the scale dependent visibility. Also, if you have a separate class of labels set up, the overall labels could be turned on, but the class is not set to visible. If it is something different than this, it might be useful to post your script to see if there may be something funky happening. –  Get Spatial Apr 23 '13 at 1:56
1  
I see a couple of things right off in your for feature in features: loop that are causing your issues. The reason you are getting the same image for each feature is that you are not changing the zoom extent when you rotate through your features. This would happen in the df.extent function that you have commented out. Figure out how to make that adjust and you should start to see differences. Also, your scale isn't being set, so this could be affecting the labeling at output. I encourage you, as in your other question, to look at the help, and try to better understand arcpy coding. –  Get Spatial Apr 23 '13 at 2:49
    
I'll try to take a stab at this later to give you some assistance. Syntax is important, so understanding the inputs in each function will help you ensure they fit together properly. –  Get Spatial Apr 23 '13 at 2:51
    
@GetSpatial, I really appreciate your advice, however am continuing to run into a wall on this. I've tried uncommenting out the df.extent. = graffitilyr.getSelectedExtent(), which changes nothing; I've tried changing the value from True to False, also changes nothing; have tried changing the order of the statements, which makes the data go away in the output, and have spent extensive time looking at various help pages. There don't seem to be a whole lot of options for manipulating the inputs of the df.extent=getSelected, and all of the examples are simple: df.extent = lyr.getSelectedExtent() –  David Meek Apr 23 '13 at 13:25
    
additionally, I understand that syntax is important, and logic is important, and it's the two that work together. To me, as a beginner, this seems correct (dangerous, I know!), because it has the logic of select feature, get selected extent, zoom to feature, and so on. In terms of your point about setting the scale, that's what I've tried to do with the df.scale = df.scale * .004, the *.004 being that I want this at a really large scale and after a bunch of trial and error found this to be the way. Any more hints that you could provide to help the learning process would be much appreciated –  David Meek Apr 23 '13 at 13:28
add comment

1 Answer

up vote 3 down vote accepted

Finally had a chance to take a stab at this script. Below is what I came up with, but first, some comments and explanation.

  1. Use the ListFields function and the OID type to return the name of the OID field. This will give you the unique identifiers of the selected features. It takes the guesswork out of getting the spelling right. It also avoids the issue of having joined tables together at some point and having multiple OID fields, but not knowing which one is the official one.
  2. I added an informational function to help with building the queries. The AddFieldDelimiters function will put in the appropriate field delimiters depending on whether the field is coming from a shapefile, FGDB, PGDB, or other source. This eliminates a lot of the chance for error. AddFieldDelimiters(arcpy)
  3. When setting up your Search Cursor, limit the number of fields that you are returning. This improves performance. Also, I switched to using the Data Access cursor which is specifically for returning attribute data. Data Access SearchCursor
  4. In both situations where you were building a query string, I moved it out of the destination function, into its own variable. This let's you build the query separately without having to deal with the surrounding function. It also let's you utilize it at different times if need be. This help reference is very useful: SQL reference for query expressions used in ArcGIS
  5. I moved the setting of the scale out of the for loop. Since you want the same scale in every export, there is no reason to zoom to the feature, then set the scale, then pan to recenter the extent. Zoom to the correct scale once, then pan around to the appropriate extent. Make sure that your coordinate systems are set properly for the data frame and also for your layer.
  6. In your original script, in order to select the feature, you were building a query using the FID field, and matching it to the count of features in your SearchCursor. This would not work because the FID of a feature does not change even when it is in a SearchCursor. I set up your SearchCursor to return the OID value which I then used as part of the Select query. Using as many functions as possible to return values, instead of entering them by hand, reduces the chance for error. This is relevant with the field name of the OID field, and the field delimiters.
  7. At the end, I included the code provided by @Tom to append all of the exported ".pdf" files to a single ".pdf". This is from his answer to your other questions: Possible to use wildcard in .pdf Append?

On to the code:

mxd = arcpy.mapping.MapDocument("C:\\temp\\Graffiti_DM3.mxd")
df = arcpy.mapping.ListDataFrames(mxd, "*")[0]
graffitilyr=arcpy.mapping.ListLayers(mxd, "*", df)[0]

#Find OID Field Name
oidfieldname = arcpy.ListFields(graffitilyr,"","OID")[0].name

#Longer but possibly more robust method
#oidfield = arcpy.ListFields(graffitilyr,"","OID")[0]
#oidfieldname = oidfield.name

queryfield = "Incident_Z"

newquery = arcpy.AddFieldDelimiters(graffitilyr,queryfield) + " = 10003"
graffitilyr.definitionQuery=newquery

#Fill List of features - Limit attribute return to OID field only for speed.  Include other fields as necessary.
features = arcpy.da.SearchCursor(graffitilyr,"OID@")
count = 1

print "let's get started"

#Set Dataframe Scale
#Parameter instructions require use of numerical(doubl) value, so no quotes are necessary.
df.scale = 1000

for feature in features:
        df.rotation = "0"
        #Build Select Query
        selectexpression = arcpy.AddFieldDelimiters(graffitilyr,oidfieldname) + " = " + feature[0]
        arcpy.SelectLayerByAttribute_management(graffitilyr, "NEW_SELECTION", selectexpression)

        #Pan to Selected Feature Extent
        df.panToExtent(graffitilyr.getSelectedExtent())

        arcpy.RefreshActiveView()

        outpdf="C:\\temp\\" + str(count) + ".pdf"
        arcpy.mapping.ExportToPDF(mxd,outpdf)

        #Add pdf to list for append to complete pdf
        pdfList.append(outpdf)

        #Increment count
        count += 1

#Create new pdf to consolidate all pages
pdfpath="C:\\temp\\pdfbook.pdf"
pdfDoc = arcpy.mapping.PDFDocumentCreate(pdfpath)

#Append all pdf pages in list to one new pdf
for aPdf in pdfList:
  pdfDoc.appendPages(aPdf)

pdfDoc.saveAndClose()

del features
del pdfDoc

Give this a shot and see how it works. The problems that I could see arising may relate to capitalization of function names. I sometimes miss which letters need to be capitalized, and Python can be finicky about this.

Hopefully this process has helped improve your knowledge of Python and arcpy for ArcGIS. There is a lot of utility in learning both. I encourage you to check out the help resources for ArcGIS:

Reviewing the documentation and code samples in these places will help you immensely if you are interested in becoming better at Python.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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