Select to view content in your preferred language

Batch Apply Definition Query to all layers (within MXD)

4785
4
Jump to solution
04-01-2014 07:09 PM
ArvinD
by
Emerging Contributor
Hey Guys,
So here's the issue


  • I have multiple mxds in a folder

  • there are subfolders within this parent foder (e.g. c:\Temp\Folder1 etc)

  • Each MXD has varying number of layers/feature classes

  • Some MXDs have layer groups

  • The query I want to apply is so: "VALIDATIONSTATE = 3"

  • All layers/FCs have the field above (VALIDATIONSTATE) so no worries there (Except of course non-vectos etc)

Is there any way I can

  1. Apply this en masse for each mxd?

  2. If yes, would it be possible to apply en masse, to each mxd, for a given folder? (I'm willing to forego applying to subfolders, and just moving everything to one folder if need be)

I've tried so many code snippets online to no avail. Any help would be appreicated!!
Thanks!
Tags (2)
0 Kudos
1 Solution

Accepted Solutions
AdamCox1
Deactivated User
Hi there, you can definitely do this, subfolders and all.  No file moving necessary.  Here is the skeleton of the code you will need:
import os, arcpy  #here's an example of how to run through all the layers in an mxd def SetDefQueries(mxdobject, defquery):     fixed_layers = []     for layer in arcpy.mapping.ListLayers(mxdobject):          #this should weed out the group layers and rasters         if layer.supports("DEFINTIONQUERY"):             fixed_layers.append(layer.name)             layer.definitionQuery = defquery      #have the function return a list summary of the layers that were changed (for fun)     return fixed_layers  #create and print query query = '"VALIDATIONSTATE" = 3' #may have to fix the syntax of this statement depending on the field type arcpy.AddMessage(query)  #to go through all of the folder, use os.walk(), you can find documentation on the python website for path, dirs, files in os.walk(top/folder/path):     for f in files:         if f.endswith(".mxd"):              #this should get you all of the mxds in all of the folders.             mxd_path = path + "\\" + f             arcpy.AddMessage(mxd_path)              #now you can make arcpy.mapping.MapDocument() objects             mxd = arcpy.mapping.MapDocumentmxd_path)              #use the SetDefQuery function on the mxd             changed_layers = SetDefQuery(mxd, query)              #print a summary of what happened             arcpy.AddMessage("In {}:".format(mxd_path))             lyrs_summary = "\n  ".join(changed_layers)             arcpy.AddMessage(lyrs_summary)              #save the mxd at the end (won't work if you have it open)             mxd.save() 


You may need to do a little bit of trouble shooting, but this should serve as a good basis for what you need in the end.  You could run it straight from a .py file on the desktop if you just change the arcpy.AddMessage() pieces to normal print statements.  Also, this is from my experience in 10.0, but I'm fairly certain that these things work the same way in 10.x

View solution in original post

0 Kudos
4 Replies
AdamCox1
Deactivated User
Hi there, you can definitely do this, subfolders and all.  No file moving necessary.  Here is the skeleton of the code you will need:
import os, arcpy  #here's an example of how to run through all the layers in an mxd def SetDefQueries(mxdobject, defquery):     fixed_layers = []     for layer in arcpy.mapping.ListLayers(mxdobject):          #this should weed out the group layers and rasters         if layer.supports("DEFINTIONQUERY"):             fixed_layers.append(layer.name)             layer.definitionQuery = defquery      #have the function return a list summary of the layers that were changed (for fun)     return fixed_layers  #create and print query query = '"VALIDATIONSTATE" = 3' #may have to fix the syntax of this statement depending on the field type arcpy.AddMessage(query)  #to go through all of the folder, use os.walk(), you can find documentation on the python website for path, dirs, files in os.walk(top/folder/path):     for f in files:         if f.endswith(".mxd"):              #this should get you all of the mxds in all of the folders.             mxd_path = path + "\\" + f             arcpy.AddMessage(mxd_path)              #now you can make arcpy.mapping.MapDocument() objects             mxd = arcpy.mapping.MapDocumentmxd_path)              #use the SetDefQuery function on the mxd             changed_layers = SetDefQuery(mxd, query)              #print a summary of what happened             arcpy.AddMessage("In {}:".format(mxd_path))             lyrs_summary = "\n  ".join(changed_layers)             arcpy.AddMessage(lyrs_summary)              #save the mxd at the end (won't work if you have it open)             mxd.save() 


You may need to do a little bit of trouble shooting, but this should serve as a good basis for what you need in the end.  You could run it straight from a .py file on the desktop if you just change the arcpy.AddMessage() pieces to normal print statements.  Also, this is from my experience in 10.0, but I'm fairly certain that these things work the same way in 10.x
0 Kudos
ArvinD
by
Emerging Contributor
It worked! Thanks mate!

🙂
0 Kudos
ArvinD
by
Emerging Contributor
Okay - so now thanks to that very helpful snippet, I have been successfully able to run the code.

I thought I could make it so that it ADDs the definition query to the layers IF there was one existing. So the I've added the following:

#use the SetDefQuery function on the mxd
            if layer.definitionQuery == True: #if a definitionQuery Exists...
                addquery = layer.definitionQuery + "AND" + query + "=" + "\"" + value + "\"" #Add new to old
            else:
            changed_layers = SetDefQueries(mxd, query)


THen it's giving me
"NameError: name 'layer' is not defined"
Is this right? Even though this should have been defined with 'defquery' earlier?


(Obviously sorry for the n00b ness.)
0 Kudos
AdamCox1
Deactivated User
Yeah, you'll have to make that modification within the function itself, not after you call it later in the script.  The following code should work.  One note, an empty definition query doesn't equal False, it's just an empty string, "".


#just copy and paste this into the corresponding place in the SetDefQuery function
    if layer.supports("DEFINITIONQUERY"):
            fixed_layers.append(layer.name)
            
            #get existing definition query
            exdefquery = layer.definitionQuery
            
            #if the existing query is empty, set the normal defquery
            if exdefquery == "":
                layer.definitionQuery = defquery

            #otherwise, make a combination defquery 
            else:
                layer.definitionQuery = "{0} AND {1}".format(exdefquery, defquery)


0 Kudos