Find by attribute tool to return original ObjectID and in correct spatial reference

515
1
03-10-2012 11:39 AM
ScottSugden
New Contributor III
Hi,

Using a GP tool (via SOAP API) I am trying create a 'Find by attribute tool' to that returns the original/searched layer ObjectID and geometry in the correct spatial reference/coordinate system. I have no problems passing the find attribute values, selecting the correct layer (from a mxd) to search and returning some results. My issue is that I can only either:
'1' Return the rows in the correct mxd spatial reference but with autogenerated ObjectIDs (not the original objectids that I require) or
'2' Return the rows with the correct searched layer ObjectIDs but in the searched layer coordinate system rather than the mxd coordinate system

I have tried various approaches to get result '1' including using:
arcpy.SearchCursor eg

mxd = arcpy.mapping.MapDocument(MXD_PATH)
df = arcpy.mapping.ListDataFrames(mxd)[0]
sr = df.spatialReference
arcpy.env.outputCoordinateSystem = sr
layer = arcpy.mapping.ListLayers(mxd, CADASTRE_LAYER_NAME)[0]
rowsSearch = arcpy.SearchCursor(layer, whereSql)
fc = arcpy.CreateFeatureclass_management("in_memory", "tempFindLotDpFc", "POLYGON", layer)
rowsNew = arcpy.InsertCursor(fc)
for rowSearch in rowsSearch:
   rowsNew.insertRow(rowSearch)
fs = arcpy.FeatureSet()
fs.load(fc)


arcpy.Select_analysis eg

mxd = arcpy.mapping.MapDocument(MXD_PATH)
df = arcpy.mapping.ListDataFrames(mxd)[0]
sr = df.spatialReference
arcpy.env.outputCoordinateSystem = sr
layer = arcpy.mapping.ListLayers(mxd, CADASTRE_LAYER_NAME)[0]
fc = arcpy.CreateFeatureclass_management("in_memory", "tempFindLotDpFc", "POLYGON", "", "", "", sr)
arcpy.Select_analysis(layer, fc, whereSql)
fs = arcpy.FeatureSet()
fs.load(fc)


I have tried updating the field OBJECTID in the fc but it is always read only. I have also tried using tables instead of feature classes with no success as OBJECTID is still read only.

Method 2 uses something like:

mxd = arcpy.mapping.MapDocument(MXD_PATH)
df = arcpy.mapping.ListDataFrames(mxd)[0]
sr = df.spatialReference
arcpy.env.outputCoordinateSystem = sr
layer = arcpy.mapping.ListLayers(mxd, CADASTRE_LAYER_NAME)[0]
arcpy.MakeTableView_management(layer, "tv", whereSql)
fs = arcpy.FeatureSet()
fs.load("tv")


Any suggestions would be greatly appreciated. Thanks
Tags (2)
0 Kudos
1 Reply
ScottSugden
New Contributor III
For those interested I solved this as follows:

'''----------------------------------------------------------------------------------
 Tool Name:     FindLotDP
 Source Name:   FindLotDP.py
 Version:       ArcGIS 10.0
 Author:        Spatial Intelligence
 Arguments:     Lot (optional)
                Section (optional)
                DP (optional)
 Description:   Finds a Lot/Section/DP in the Cadastre layer
----------------------------------------------------------------------------------'''
import arcpy as arcpy
import ErrorUtils as ERROR
WORKSPACE_NAME = r"\\server7\arcgis_server_resources\Connection_to_Server1.sde"     #Name of the workspace (connection) that contains the Cadastre feature class
MXD_PATH = r"\\server7\arcgis_server_resources\MSB.mxd"                             #Name of the workspace (mxd) that contains the Cadastre feature class
CADASTRE_LAYER_NAME = "NSW Cadastre"                                                #The name of the cadastre feature class that contains the Lot, Section & DP fields
LOT_COLUMN_NAME = "LOTNUMBER"                                                       #The name of the lot column in the cadastre feature class
SECTION_COLUMN_NAME = "SECTIONNUMBER"                                               #The name of the section column in the cadastre feature class
DP_COLUMN_NAME = "PLANNUMBER"                                                       #The name of the dp column in the cadastre feature class
def buildWhereSQL(lot, section ,dp):
    sql = ""
    if lot != "":
        if section != "":
            if dp != "":
                sql = LOT_COLUMN_NAME + " = '" + lot + "' and " + SECTION_COLUMN_NAME + " = '" + section + "' and " + DP_COLUMN_NAME + " = '" + dp + "'"
            else:
                sql = LOT_COLUMN_NAME + " = '" + lot + "' and " + SECTION_COLUMN_NAME + " = '" + section + "'"
        else:
            if dp != "":
                sql = LOT_COLUMN_NAME + " = '" + lot + "' and " + DP_COLUMN_NAME + " = '" + dp + "'"
            else:
                sql = LOT_COLUMN_NAME + " = '" + lot + "'"
    else:
        if section != "":
            if dp != "":
                sql = SECTION_COLUMN_NAME + " = '" + section + "' and " + DP_COLUMN_NAME + " = '" + dp + "'"
            else:
                sql = SECTION_COLUMN_NAME + " = '" + section + "'"
        else:
            if dp != "":
                sql = DP_COLUMN_NAME + " = '" + dp + "'"
            else:
                sql = ""        
    return (sql)
def getFieldTypeForAddField(fieldType):
    fieldTypeForAddField = ""
    if fieldType == "SmallInteger":      
        fieldTypeForAddField = "SHORT"
    if fieldType == "Integer":      
        fieldTypeForAddField = "LONG"
    if fieldType == "Single":      
        fieldTypeForAddField = "DOUBLE"
    if fieldType == "Double":      
        fieldTypeForAddField = "FLOAT"
    if fieldType == "String":      
        fieldTypeForAddField = "TEXT"
    if fieldType == "Date":      
        fieldTypeForAddField = "DATE"
    if fieldType == "OID":      
        fieldTypeForAddField = "LONG"
    if fieldType == "Geometry":      
        fieldTypeForAddField = ""
    if fieldType == "Blob":      
        fieldTypeForAddField = "BLOB"
        
    return (fieldTypeForAddField)
def main():
    arcpy.env.overwriteOutput = True #so that "tempFindLotDpFc" is over written each time
    
    # Get the input argument values
    arcpy.AddMessage("Building SQL")
    print "Building SQL"
    lot = arcpy.GetParameterAsText(0)
    section = arcpy.GetParameterAsText(1)
    dp = arcpy.GetParameterAsText(2)
    # Debug values
##    lot = "2"
##    dp = "752468"
    
    # Get SQL
    whereSql = buildWhereSQL(lot, section, dp)
    print whereSql
    if whereSql == "":
        arcpy.AddMessage("No search criteria")
        print "No search criteria"
    else:
        try:
            arcpy.env.workspace = WORKSPACE_NAME
           
            #Set mxd
            arcpy.AddMessage("Getting mxd")
            print "Getting mxd"
            mxd = arcpy.mapping.MapDocument(MXD_PATH)
            #Get and spatial reference for output
            arcpy.AddMessage("Getting spatial reference")
            print "Getting spatial reference"
            df = arcpy.mapping.ListDataFrames(mxd)[0]
            sr = df.spatialReference
            arcpy.env.outputCoordinateSystem = sr
            
            #Layer index
            #Dynamic method - useful if you are changing layer order/list frequently
            arcpy.AddMessage("Getting layer index")
            print "Getting layer index"
            layerId = -1
            layers = arcpy.mapping.ListLayers(mxd)
            for x in xrange(0, len(layers) - 1):
                if layers.name == CADASTRE_LAYER_NAME:
                    layerId = x
                    break
            #Or hard code the value for speed
            #layerId = 6
            
            # Find
            arcpy.AddMessage("Getting layer")
            print "Getting layer"
            layer = arcpy.mapping.ListLayers(mxd, CADASTRE_LAYER_NAME)[0]
            fieldList = arcpy.ListFields(layer.datasetName)
            #This approach returns the correct value for ObjectID and the polygon in the correct coordinate system. It also returns an additional column OID which is the auto-generated value for the return fc
            arcpy.AddMessage("Creating feature class")
            print "Creating feature class"
            fc = arcpy.CreateFeatureclass_management("in_memory", "tempFindLotDpFc", "POLYGON", layer)
            for field in fieldList:
                if field.name != "SHAPE":
                    arcpy.AddField_management(fc, field.name, getFieldTypeForAddField(field.type), field.precision, field.scale, field.length, field.aliasName, field.isNullable, field.required, field.domain)
            arcpy.AddMessage("Selecting features")
            print "Selecting features"
            searchRows = arcpy.SearchCursor(layer, whereSql)
            newRows = arcpy.InsertCursor(fc)
            for searchRow in searchRows:
                newRow = newRows.newRow()
                for field in fieldList:
                    if field.name != "SHAPE.AREA" and field.name != "SHAPE.LEN":    #setValue or getValue does not like these field names
                        newRow.setValue(field.name, searchRow.getValue(field.name))
                newRows.insertRow(newRow)
            del newRows
            del searchRows
            del searchRow
            del newRow
          
            arcpy.AddMessage("Getting feature set")
            print "Getting feature set"
            fs = arcpy.FeatureSet()
            fs.load(fc)
            # Return
            arcpy.AddMessage("Getting return")
            print "Getting return"
            arcpy.SetParameter(3, layerId)
            arcpy.SetParameter(4, fs)
            arcpy.AddMessage("Finished")
            print "Finished"
        except Exception, e:
            import traceback
            map(arcpy.AddError, traceback.format_exc().split("\n"))
            arcpy.AddError(str(e))
            print str(e)
    #Return all messages
    for msg in range(0, arcpy.GetMessageCount()):
        arcpy.AddReturnMessage(msg)
if __name__ == '__main__':
    main()


0 Kudos