Map To KML (Conversion) with definition query

4514
8
Jump to solution
05-20-2014 11:44 PM
GinoMellino
Occasional Contributor
Hi All,

My apologies if this should have been posted elsewhere (python maybe?) - please move if it is.

I am attempting to use python to iterate a list of properties and run the MapToKML tool so that it will create a KML showing that cadastral parcel and any surrounding data within the other layers in the MXD. The subject lot is specified by using a definition query on the subject/cadastral layer to show ONLY that lot - the extent of the layer is then used with the MapToKML tool so that the surrounds are picked up.

This all works fine. The issue I am having is that the same extents worth of parcels are being exported from the subject layer also - i.e. Map To KML is not honouring the definition query (see attached - the subject layer is the heavier black line). Is there a way to get this to honour the definition query? Should I be using the Layer To KML (Conversion) and iterating over layers individually? Am I going about this whole process in completely the wrong way - I am not sure - any advice/help welcome 😉

Thanks in advance,
Gino
0 Kudos
1 Solution

Accepted Solutions
GinoMellino
Occasional Contributor
Hi Kevin,

After some re-jigging of the code it appears to be working as you say now, still in 10.1. I believe (not 100% sure on this) the issue was fixed by using the "CURRENT" MXD and making sure .save() was performed on the map document object after the definition query was set. Thank you for your help. I have attached the code in case anyone else may find it useful.

Regards,
Gino

import arcpy import os import re import datetime  #-------------------PARAMETERS-------------------------------------------------- textfilePath = arcpy.GetParameterAsText(0) # Path to text file with parcel descriptions. outputFolder = arcpy.GetParameterAsText(1) # Out folder path exportdataCheckbox = arcpy.GetParameterAsText(2) # Checkbox to export data to a geodatabase. #-------------------------------------------------------------------------------   def ReadTextFile(path):     textFile = open(path, "r")     lines = textFile.readlines()     textFile.close     return lines   def ExportKMZ(lotplan):     try:         # Output file name. If a file of the same name exists then delete it         # and create a new file          outKMZ = os.path.join(outputFolder,lotplan, "lot" + lotplan + "_" + today + ".kmz")         if arcpy.Exists(outKMZ):               os.remove(outKMZ)          # Get layer extent rectangle and remove superfluos information. The         # remaining coordinates should be in format LL UR         extent = subjectLayer.getSelectedExtent(False)          cleanextent = re.sub('[A-Za-z]', '', str(extent))          # Create KMZ         arcpy.MapToKML_conversion(mxd.filePath,"KMZExportMap", outKMZ,"0","NO_COMPOSITE","VECTOR_TO_IMAGE",cleanextent,"1024","96","CLAMPED_TO_GROUND")          arcpy.AddMessage("KMZ exported: " + outKMZ)     except Exception, e:         arcpy.AddError(e.message)         print e.message   def CreateOutputFolder(cleanlotplan):     # Create a project folder if needed     global outFolder     outFolder = os.path.join(outputFolder,cleanlotplan)     if not os.path.exists(outFolder):         os.makedirs(outFolder)   def ExportSubject(cleanlotplan):      try:          # Create a project geodatabase if needed         if not arcpy.Exists(os.path.join(outFolder, "Data_" + today +".gdb")):             arcpy.CreateFileGDB_management(outFolder, "Data_" + today +".gdb")          # Create a subject layer in geodatabase         global outGDB # Create object as 'global' as it will be used 'ron         outGDB = os.path.join(outFolder, "Data_" + today +".gdb")         subjectlayerName = os.path.join(outGDB,"SubjectLot" + cleanlotplan + "_" + today)         if arcpy.Exists(subjectlayerName):             arcpy.Delete_management(subjectlayerName)          # Export subject features         arcpy.CopyFeatures_management(subjectLayer,  subjectlayerName )         arcpy.AddMessage("Subject parcels exported to: " + subjectlayerName)          del subjectlayerName      except Exception, e:             arcpy.AddError(e.message)             print e.message  def ExportDataToGeodatabase(cleanlotplan):     try:          # Get extent from 'extent_layer' object         desc = arcpy.Describe(subjectLayer)         extent = desc.extent         arcpy.env.workspace = outGDB         arcpy.AddMessage("Old Exten: " + str(arcpy.env.extent))         arcpy.env.extent = extent         arcpy.AddMessage("Old Exten: " + str(arcpy.env.extent))         # Iterate layers and export to GDB. Check to see if layer is a         # featurelayer and is not missing datasources.         layers = arcpy.mapping.ListLayers(mxd)          for layer in layers:             if "Data Group" in layer.longName and layer.isFeatureLayer == True:                  outlayerPath = os.path.join(outGDB,layer.datasetName +  "_" + today)                 arcpy.CopyFeatures_management(layer,  outlayerPath)                 arcpy.AddMessage("Layer (" +  layer.name + ") exported to: " + outlayerPath)          # Refresh view and TOC         arcpy.RefreshActiveView         arcpy.RefreshTOC       except Exception, e:         arcpy.AddError(e.message)      finally:         # Reset geoprocessing environment settings         arcpy.ResetEnvironments()   arcpy.AddMessage("Subject parcel list: " + textfilePath) arcpy.AddMessage("Output location: " + outputFolder)   # Get parcel description from .txt file lotplanList = ReadTextFile(textfilePath)   # Get MXD, etc. mxd = arcpy.mapping.MapDocument("CURRENT") df = arcpy.mapping.ListDataFrames(mxd, "KMZExportMap") [0] subjectLayer = arcpy.mapping.ListLayers(mxd,"Subject Lot Plan", df)[0]  # global variables outFolder = None outGDB = None failedexportList = []  # Get date today = re.sub('[-]',"",str(datetime.date.today()))  # Iterate items in list for lotplan in lotplanList:     try:         # Remove whitespace and capitalise lotplan         cleanlotplan = lotplan.strip().upper()         arcpy.AddMessage("Processing lot description: " + cleanlotplan)         whereClause = """"LOTPLAN" = '""" + cleanlotplan + "'"         subjectLayer.definitionQuery = whereClause          # Save mxd so the definition query is picked up in the KMZ export         mxd.save()          # Use feature count to determine if lot/plan was found.         count = int(arcpy.GetCount_management(subjectLayer).getOutput(0))          # Conditional statement to determine if a feature(s) within the subject         # layer match the lotplan used in definition query. If count is 0 then         # not matching feature were found - move to next lot/plan. If count > 0         # then the parcel has been found. Call geoprocessing and export routines         # using the parcels details to create the outputs.         if count > 0:             arcpy.AddMessage("Found parcel: " + cleanlotplan)              # Create main output folder for lot description             CreateOutputFolder(cleanlotplan)              # If selected export ESRI data             if str(exportdataCheckbox) == "true":                 ExportSubject(cleanlotplan)                 ExportDataToGeodatabase(cleanlotplan)              ExportKMZ(cleanlotplan)          else:             arcpy.AddWarning("Could not find parcel: " + cleanlotplan)             failedexportList.append(lotplan)      except Exception, e:         arcpy.AddError(e.message)      finally:         # Always remove deinition query before processing the next lotplan         subjectLayer.definitionQuery = None          # Create text file to store unfound parcel descriptions.         txtfilePath = os.path.join(outputFolder,"UnfoundLots_" + today + ".txt")         txtFile = open(txtfilePath, "a")         if len(failedexportList) > 0:             for lot in failedexportList:                 txtFile.write(lot)         txtFile.flush()         txtFile.close()  del txtFile del failedexportList del outFolder del outGDB del subjectLayer del mxd del lotplanList 

View solution in original post

0 Kudos
8 Replies
IanMurray
Frequent Contributor
Hi Gino,

Since you are using python on this, if you would post your code it would definitely be helpful in trying to find a solution to your problem. Also you say you have a list of properties that you are trying to do this for, are they all seperate files, or individual records in a single attribute table?
0 Kudos
GinoMellino
Occasional Contributor
Hi Ian,

See below for my code - please excuse my general messiness as I am new to python. The list of cadastral parcels is just a .txt file with a separate description (lot/plan) on each line. Thanks for you reply, any help is appreciated 🙂

Cheers,
Gino

#-------------------PARAMETERS--------------------------------------------------
textfilePath = r"C:\_TEMP_SSD_PERFORMANCE\ToKML Test\SLATS1011_LotPlans2.txt"
mxdPath = r"C:\_TEMP_SSD_PERFORMANCE\ToKML Test\ExportToKMZ.mxd"
outputFolder = r"C:\_TEMP_SSD_PERFORMANCE\ToKML Test\Outputs"
#-------------------------------------------------------------------------------

import arcpy
import os
import re


def ReadTextFile(path):
    textFile = open(path, "r")
    lines = textFile.readlines()
    textFile.close
    return lines


def Extract(lotplan, extent):
    try:
        outKMZ = os.path.join(outputFolder, lotplan + ".kmz")
        if arcpy.Exists(outKMZ):
              os.remove(outKMZ)

        cleanextent = re.sub('[A-Za-z]', '', str(extent))

        arcpy.MapToKML_conversion(mxdPath,"KMZExportMap", outKMZ,"0","NO_COMPOSITE","VECTOR_TO_IMAGE",cleanextent,"1024","96","CLAMPED_TO_GROUND")
    except Exception, e:
        print e.message




# Get parcel description from .txt file
lotplanList = ReadTextFile(textfilePath)

# Get MXD, etc.
mxd = arcpy.mapping.MapDocument(mxdPath)
df = arcpy.mapping.ListDataFrames(mxd, "KMZExportMap") [0]
subjectLayer = arcpy.mapping.ListLayers(mxd,"Subject Area", df)[0]

# Iterate parcels, apply definition query and export
for lotplan in lotplanList:
    cleanlotplan = lotplan.strip()
    whereClause = """"LOTPLAN" = '""" + cleanlotplan + "'"
    subjectLayer.definitionQuery = whereClause
    extent = subjectLayer.getSelectedExtent(False)
    print cleanlotplan

    Extract(cleanlotplan,extent)

    subjectLayer.definitionQuery = None


del subjectLayer
del mxd
del lotplanList
0 Kudos
KevinHibma
Esri Regular Contributor
Your code looks good. Try saving a copy of the MXD and pass that into the tool.


#-------------------PARAMETERS--------------------------------------------------
textfilePath = r"C:\_TEMP_SSD_PERFORMANCE\ToKML Test\SLATS1011_LotPlans2.txt"
mxdPath = r"C:\_TEMP_SSD_PERFORMANCE\ToKML Test\ExportToKMZ.mxd"
outputFolder = r"C:\_TEMP_SSD_PERFORMANCE\ToKML Test\Outputs"
#-------------------------------------------------------------------------------

import arcpy
import os
import re


def ReadTextFile(path):
    textFile = open(path, "r")
    lines = textFile.readlines()
    textFile.close
    return lines


def Extract(lotplan, extent, tempMXD):
    try:
        outKMZ = os.path.join(outputFolder, lotplan + ".kmz")
        if arcpy.Exists(outKMZ):
              os.remove(outKMZ)

        cleanextent = re.sub('[A-Za-z]', '', str(extent))

        arcpy.MapToKML_conversion(tempMXD,"KMZExportMap", outKMZ,"0","NO_COMPOSITE","VECTOR_TO_IMAGE",cleanextent,"1024","96","CLAMPED_TO_GROUND")
    except Exception, e:
        print e.message




# Get parcel description from .txt file
lotplanList = ReadTextFile(textfilePath)

# Get MXD, etc.
mxd = arcpy.mapping.MapDocument(mxdPath)
df = arcpy.mapping.ListDataFrames(mxd, "KMZExportMap") [0]
subjectLayer = arcpy.mapping.ListLayers(mxd,"Subject Area", df)[0]

# Iterate parcels, apply definition query and export
for lotplan in lotplanList:
    cleanlotplan = lotplan.strip()
    whereClause = """"LOTPLAN" = '""" + cleanlotplan + "'"
    subjectLayer.definitionQuery = whereClause
    extent = subjectLayer.getSelectedExtent(False)
    print cleanlotplan

    #save a copy of the mxd with the updated def query 
    tempMXD = os.path.join(arcpy.env.scratchFolder, "tempmxd.mxd")
    mxd.saveACopy(tempMXD)

    Extract(cleanlotplan,extent, tempMXD)

    #delete that temp mxd
    os.remove(tempMXD)

    subjectLayer.definitionQuery = None


del subjectLayer
del mxd
del lotplanList
0 Kudos
GinoMellino
Occasional Contributor
Hi Kevin,

I have plugged an MXD into it and the extraction happens fine...except...the definition query is not honoured by the MapToKML tool. I need the subject lot to be the only parcel from the cadastral layer to be exported to KMZ. At the moment the script will export that parcel and all other parcels from the cadastral layer which are within the extent here.
 extent = subjectLayer.getSelectedExtent(False)
I think this is just the way the tool works and have now resolved to finding a workaround. The options I am considering are exporting the parcel to a new temporary layer and running MapToKML or attempting to use a uniquevaluerenderer and only add the value for the subject parcel - I am not having any luck with the latter at the moment. When I have a suitable workaround I will post but in the mean time any help is greatly appreciated.

Cheers,
Gino
0 Kudos
KevinHibma
Esri Regular Contributor
What version are you using?
I just tried in 10.2.2 and a def query on the layer in an mxd is honored.
0 Kudos
GinoMellino
Occasional Contributor
Hi Kevin,

That could be the difference - I am still running 10.1 SP1 as that is what the internal clients I support are running and also I still believe it is the official version for our Dept according to IT 😞

Perhaps I will need to convince IT to upgrade.

Thanks for you help! If I get a workable solution for this in 10.1 I will post it.

Cheers,
Gino
0 Kudos
KevinHibma
Esri Regular Contributor
Gino,

I dont know if you'll see a difference between 10.1 sp1 and 10.2.2 - I dont recall a lot of issues in regards to KML being fixed there. Most of these issues were fixed in 10.0 sp1-5.

That said, I went back and tested with a cadastral layer as I thought maybe that has something to do with it.
I'm not an expert with the fabric layer, but my output KMZ looks the same as the fabric layer inside ArcMap that has a def query.
I put the def query on my yellow colored parcels layer - you can see that the two images look the same. (without the def query all parcels are yellow)
0 Kudos
GinoMellino
Occasional Contributor
Hi Kevin,

After some re-jigging of the code it appears to be working as you say now, still in 10.1. I believe (not 100% sure on this) the issue was fixed by using the "CURRENT" MXD and making sure .save() was performed on the map document object after the definition query was set. Thank you for your help. I have attached the code in case anyone else may find it useful.

Regards,
Gino

import arcpy import os import re import datetime  #-------------------PARAMETERS-------------------------------------------------- textfilePath = arcpy.GetParameterAsText(0) # Path to text file with parcel descriptions. outputFolder = arcpy.GetParameterAsText(1) # Out folder path exportdataCheckbox = arcpy.GetParameterAsText(2) # Checkbox to export data to a geodatabase. #-------------------------------------------------------------------------------   def ReadTextFile(path):     textFile = open(path, "r")     lines = textFile.readlines()     textFile.close     return lines   def ExportKMZ(lotplan):     try:         # Output file name. If a file of the same name exists then delete it         # and create a new file          outKMZ = os.path.join(outputFolder,lotplan, "lot" + lotplan + "_" + today + ".kmz")         if arcpy.Exists(outKMZ):               os.remove(outKMZ)          # Get layer extent rectangle and remove superfluos information. The         # remaining coordinates should be in format LL UR         extent = subjectLayer.getSelectedExtent(False)          cleanextent = re.sub('[A-Za-z]', '', str(extent))          # Create KMZ         arcpy.MapToKML_conversion(mxd.filePath,"KMZExportMap", outKMZ,"0","NO_COMPOSITE","VECTOR_TO_IMAGE",cleanextent,"1024","96","CLAMPED_TO_GROUND")          arcpy.AddMessage("KMZ exported: " + outKMZ)     except Exception, e:         arcpy.AddError(e.message)         print e.message   def CreateOutputFolder(cleanlotplan):     # Create a project folder if needed     global outFolder     outFolder = os.path.join(outputFolder,cleanlotplan)     if not os.path.exists(outFolder):         os.makedirs(outFolder)   def ExportSubject(cleanlotplan):      try:          # Create a project geodatabase if needed         if not arcpy.Exists(os.path.join(outFolder, "Data_" + today +".gdb")):             arcpy.CreateFileGDB_management(outFolder, "Data_" + today +".gdb")          # Create a subject layer in geodatabase         global outGDB # Create object as 'global' as it will be used 'ron         outGDB = os.path.join(outFolder, "Data_" + today +".gdb")         subjectlayerName = os.path.join(outGDB,"SubjectLot" + cleanlotplan + "_" + today)         if arcpy.Exists(subjectlayerName):             arcpy.Delete_management(subjectlayerName)          # Export subject features         arcpy.CopyFeatures_management(subjectLayer,  subjectlayerName )         arcpy.AddMessage("Subject parcels exported to: " + subjectlayerName)          del subjectlayerName      except Exception, e:             arcpy.AddError(e.message)             print e.message  def ExportDataToGeodatabase(cleanlotplan):     try:          # Get extent from 'extent_layer' object         desc = arcpy.Describe(subjectLayer)         extent = desc.extent         arcpy.env.workspace = outGDB         arcpy.AddMessage("Old Exten: " + str(arcpy.env.extent))         arcpy.env.extent = extent         arcpy.AddMessage("Old Exten: " + str(arcpy.env.extent))         # Iterate layers and export to GDB. Check to see if layer is a         # featurelayer and is not missing datasources.         layers = arcpy.mapping.ListLayers(mxd)          for layer in layers:             if "Data Group" in layer.longName and layer.isFeatureLayer == True:                  outlayerPath = os.path.join(outGDB,layer.datasetName +  "_" + today)                 arcpy.CopyFeatures_management(layer,  outlayerPath)                 arcpy.AddMessage("Layer (" +  layer.name + ") exported to: " + outlayerPath)          # Refresh view and TOC         arcpy.RefreshActiveView         arcpy.RefreshTOC       except Exception, e:         arcpy.AddError(e.message)      finally:         # Reset geoprocessing environment settings         arcpy.ResetEnvironments()   arcpy.AddMessage("Subject parcel list: " + textfilePath) arcpy.AddMessage("Output location: " + outputFolder)   # Get parcel description from .txt file lotplanList = ReadTextFile(textfilePath)   # Get MXD, etc. mxd = arcpy.mapping.MapDocument("CURRENT") df = arcpy.mapping.ListDataFrames(mxd, "KMZExportMap") [0] subjectLayer = arcpy.mapping.ListLayers(mxd,"Subject Lot Plan", df)[0]  # global variables outFolder = None outGDB = None failedexportList = []  # Get date today = re.sub('[-]',"",str(datetime.date.today()))  # Iterate items in list for lotplan in lotplanList:     try:         # Remove whitespace and capitalise lotplan         cleanlotplan = lotplan.strip().upper()         arcpy.AddMessage("Processing lot description: " + cleanlotplan)         whereClause = """"LOTPLAN" = '""" + cleanlotplan + "'"         subjectLayer.definitionQuery = whereClause          # Save mxd so the definition query is picked up in the KMZ export         mxd.save()          # Use feature count to determine if lot/plan was found.         count = int(arcpy.GetCount_management(subjectLayer).getOutput(0))          # Conditional statement to determine if a feature(s) within the subject         # layer match the lotplan used in definition query. If count is 0 then         # not matching feature were found - move to next lot/plan. If count > 0         # then the parcel has been found. Call geoprocessing and export routines         # using the parcels details to create the outputs.         if count > 0:             arcpy.AddMessage("Found parcel: " + cleanlotplan)              # Create main output folder for lot description             CreateOutputFolder(cleanlotplan)              # If selected export ESRI data             if str(exportdataCheckbox) == "true":                 ExportSubject(cleanlotplan)                 ExportDataToGeodatabase(cleanlotplan)              ExportKMZ(cleanlotplan)          else:             arcpy.AddWarning("Could not find parcel: " + cleanlotplan)             failedexportList.append(lotplan)      except Exception, e:         arcpy.AddError(e.message)      finally:         # Always remove deinition query before processing the next lotplan         subjectLayer.definitionQuery = None          # Create text file to store unfound parcel descriptions.         txtfilePath = os.path.join(outputFolder,"UnfoundLots_" + today + ".txt")         txtFile = open(txtfilePath, "a")         if len(failedexportList) > 0:             for lot in failedexportList:                 txtFile.write(lot)         txtFile.flush()         txtFile.close()  del txtFile del failedexportList del outFolder del outGDB del subjectLayer del mxd del lotplanList 
0 Kudos