Arcattr
From DreamsteepWiki
This is my python code to manipulate attributes on GIS datasets via com32 and the arcscripting module , I am looking at using free tools instead
Arc seems to be clunky and comercial (it has some good stuff though here and there , I have to admit)
Written by Keith Legg August 2007
#import sys_file_io
import sys_data_tree
#i think this is the first experimental use of data tree
#written around nov 07 (for autodesk data transport)
import sys_arrays
import string,sys,os,traceback
#gp = win32com.client.Dispatch("esriGeoprocessing.GpDispatch.1")
try:
#import relevant modules, create geoprocessing dispatch object
import win32com.client
gp = win32com.client.Dispatch("esriGeoprocessing.gpDispatch.1")
except:
print 'WARN NO ESRI SUPPORT FROM CURRENT SHELL '
def AddPrintMessage(msg, severity):
print msg
if severity == 0: gp.AddMessage(msg)
elif severity == 1: gp.AddWarning(msg)
elif severity == 2: gp.AddError(msg)
"""
a python class to handle all operations pertaining to feature classes and the
creation/modification of attribute tables
keith legg , Sep 29 ,Nov 17 2007
"""
########################
"""
USAGE
import sys_arclink_ATTRS
#BEGIN
#foo = ESRI_ATTR_EDIT()
#SHAPEFILE = 'C:/data/Creswell_ForSale_W10.shp'
#DATABASE = 'C:/data/fucker.mdb'
###########################################
#READ ATTRNAMES,ATTRTYPES,AND ALL VALUES , INTO MEMORY FROM A FEATURE CLASS
#foo.readAttrs(SHAPEFILE)
#foo.export_to_data_tree(SHAPEFILE,'C:/reportt.txt')
##
#GET NUM ATTRS (SET FROM READ)
#print foo.NUMATTRS
#SHOW ALL ATTRTYPES
#print foo.ATTRTYPES
#SHOW ATTRNAME BY INDEX
#print foo.ATTRNAMES[3]
#SHOW ATTRVALUES BY INDEX
#print foo.ATTRVALUES[3]
#SHOW ALL FIELDS IN AN ARRAY
#print foo.ATTRNAMES
#print foo.ATTRVALUES
###################################
#TO CLEAR ALL MEMORY (BEFORE LOADING NEXT ATTR)
#foo.clearAllInternals()
###########################################
#ADD ATTR
#foo.addAttr(SHAPEFILE,'butrocker','text')
#foo.addAttr(SHAPEFILE,'ewew','float')
#foo.addAttr(SHAPEFILE,'ewew','long')
#foo.addAttr(SHAPEFILE,'ewew','double')
###########################################
#DELETE AN ATTR
#foo.delAttr(SHAPEFILE,'ewew')
###########################################
#WRITE ATTR
#inserttable = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','m']
#inserttable = [1.3,2.3,3.3,4.3,5.3,6.3,7.3,8.3,9.3,10.3,11.3,12.3,13.3,14.3,15.3]
#inserttable = [12,23,19,22,25,618,76,83,93,103,113,123,133,143,153]
#foo.writeAttrs(SHAPEFILE,'butrocker',inserttable)
###########################################
#GET GEOMETRY INFO
#foo.getGeoInfo(SHAPEFILE)
#####################################
#GET FIELD INFO
#foo.getFieldInfo(SHAPEFILE)
###########################################
#GET AN ATTRIBUTE (VALUE TABLE) BY NAME
#print foo.getFeatureAttr(SHAPEFILE,'NAME')
#GET AN ATTRIBUTE BY NAME AND VALUE ID
#print foo.getFeatureAttrValue(SHAPEFILE,'FID',5)
#GET AN ATTRIBUTE BY PART ?
#foo.getPartAttr(SHAPEFILE)
"""
####################################################################################
class ESRI_ATTR_EDIT:
def __init__(self):
self.NUMATTRS = 0
self.ATTRVALUES = [[]]
#
self.ATTRNAMES = []
self.ATTRTYPES = []
self.Editable = []
self.Length = []
self.Type = []
self.Scale = []
self.Domain = []
self.isMultiPart = []
self.partCount = []
self.centroid = []
self.length = []
self.firstPoint = []
self.lastPoint = []
self.area = []
self.length = []
self.firstPoint = []
self.lastPoint = []
########################
###########################
###########################
def clearAllInternals(self):
self.NUMATTRS = 0
self.ATTRVALUES = []
self.ATTRNAMES = []
self.ATTRTYPES = []
self.Editable = []
self.Length = []
self.Type = []
self.Scale = []
self.Domain = []
self.isMultiPart = []
self.partCount = []
self.centroid = []
self.length = []
self.firstPoint = []
self.lastPoint = []
self.area = []
self.length = []
self.firstPoint = []
self.lastPoint = []
###########################
def checkfileexists(self,obj):
if os.path.lexists(obj):
return 1
if os.path.lexists(obj)==0:
return 0
#####################
def checkfieldexists(self,obj,field):
attrs = []
attrs = self.listAttrs(obj)
for attr in attrs:
if attr == field:
return 1
return 0
#####################
def getnumattrs(self,obj):
attrs = []
attrs = self.listAttrs(obj)
count = 0
for attr in attrs:
count=count+1
return count
#####################
#def getnumattrs(self,obj):
# attrs = []
# attrs = self.listParts(obj)
#count = 0
#for attr in attrs:
# count=count+1
#return count
#####################
#def addSubType
#def removeSubType
#def setdefualtsubtype
#def setDefualt ()
#####################
# def createEmpty_MDB():
# def createEmpty_SHP():
#####################
"""
as a matter of triva this was the first use of the data graph
it was made around August 2007, just prior to the Autodesk UVIZ 360 challenge
in fact the output of this is seen, imported in maya at the end of the video
"""
def export_to_data_tree (self,feature,filename):
if self.checkfileexists(feature)==0:
raise (feature+' DOES NOT EXIST ')
if self.checkfileexists(feature):
###CLEAR MEMORY TO BEGIN
self.clearAllInternals()
###READ FEATURE ATTRS
self.readAttrs(feature)
#print foo.ATTRVALUES
#test = self.ATTRVALUES[0]
names = self.ATTRNAMES
#print 'DEBUG '
#print names
cleanname = feature.replace('.','')
cleanname = cleanname.replace(':','')
cleanname = cleanname.replace('/','')
cleanname = cleanname.replace('\\','')
DG = sys_data_tree.data_graph( ('FC_'+cleanname) )
###
countme = 0
for name in names:
ATR = []
temps = self.ATTRVALUES[countme]
for temp in temps:
ATR.append('_')
ATR2 = self.ATTRVALUES[countme]
newnode = sys_data_tree.node_base((name+'_FIELD'),ATR,ATR2)
DG.add(newnode)
countme=countme+1
###
#DG.dumpall()
DG.save_graph_file(filename)
#####################
#####################
# def insertRow(self,fc,attrname,fieldtype):
#####################
def deleteRow (self,feature):
# Create update cursor for feature class
rows = gp.UpdateCursor(feature)
row = rows.Next()
while row: # Delete all rows that have a roads type of 4
#if row.road_type == 4:
# rows.DeleteRow(row)
row = rows.Next()
if rows:
del rows
if row:
del row
#####################
"""
DEBUG UNIMPLEMENTED
this will look for a field and matching field
then attempt to find value of first field in a list and apply a corresponding value to a second field
this is to match different tables in arbitrary order
DEBUG UNIMPLEMENTED
"""
#match_tables(SHAPEFILE,'FS_ML_NUM','LEGAL',VALID_ML,VALID_LEG )
def match_tables(self,featureclass,field1,field2,table1,table2):
if self.checkfileexists(featureclass)==0:
print featureclass+' DOES NOT EXIST '
if self.checkfileexists(featureclass):
if len(table1) == 0:
print 'ERROR table1 IS EMPTY '
if len(table2) == 0:
print 'ERROR table2 IS EMPTY '
###
if self.checkfieldexists(featureclass,field1)==0:
print 'field1 does not exist '
if self.checkfieldexists(featureclass,field2)==0:
print 'field2 does not exist '
##
#self.
SETONE = self.getFeatureAttr(featureclass,field1)
SETTWO = self.getFeatureAttr(featureclass,field2)
#print SETONE
#print SETTWO
#raw_input()
#LOOKUP =
#RETRNVAL = sys_arrays.lookupMatchedValues( LOOKUP,table1,table2)
#############DEBUG UNTESTED , LINKED IN THE ATTR VARIABLE NOV,1 2007
#for value in valuetable:
# print 'SORTING POLYGON '+ ' #'+str(count)+'# ' + str(value)
# gp.SelectLayerByAttribute( "lyr","ADD_TO_SELECTION",(attr+'= '+str(value) ) )
# count = count +1
#gp.CopyFeatures("lyr", output)
#####################
"""
this function "filters" a shapefile based on matching attributes
(attr is the attribute to look for (MAKE SURE IT EXISTS !)
valuetable is the list of values to attempt to match
input_objects = exsisting shapefile (database) to sort
output = shape file to create
)
"""
def filter_layers(self,attr,valuetable,input_objects,output):
if self.checkfileexists(input_objects[0]):
gp.MakeFeatureLayer(input_objects[0],"lyr")
elif self.checkfileexists(input_objects):
gp.MakeFeatureLayer(input_objects,"lyr")
else :
print 'ESRI_ATTR_EDIT.filter_layers: error no type defined '+input_objects
count = 0
if len(valuetable) == 0:
print 'ERROR valuetable IS EMPTY '
#############
for value in valuetable:
print 'SORTING POLYGON '+ ' #'+str(count)+'# ' + str(value)
gp.SelectLayerByAttribute( "lyr","ADD_TO_SELECTION",(attr+'= '+str(value) ) )
count = count +1
gp.CopyFeatures("lyr", output)
###QUEREY ATTR EXISTS
########################################
########################################
##QUEREY VALUES FOR AN ATTRIBUTE
def getFeatureAttr(self,fc,attrname):
OUTPUT = []
rows = gp.searchCursor(fc)
row = rows.Next()
while row:
foo = ''
exec ('foo=row.'+attrname)
OUTPUT.append( foo )
row = rows.Next()
#########
if row:
del row
if rows:
del rows
##########
return OUTPUT
########################################
###CREATE AN ATTRIBUTE
"""
TYPES ARE
Text - Names or other textual qualities.
Float - Numeric values with fractional values within a specific range.
Double - Numeric values with fractional values within a specific range.
Short - Numeric values without fractional values within a specific range; coded values.
Long - Numeric values without fractional values within a specific range.
Date - Date and/or Time.
Blob - images or other multimedia.
"""
def addAttr(self,fc,attrname,fieldtype):
try :
gp.addfield(str(fc),str(attrname),str(fieldtype))
#keep count
self.NUMATTRS=self.NUMATTRS+1
except:
print '## ESRI_ATTR_EDIT.addAttr : FAILED '
tb = sys.exc_info()[2]
tbinfo = traceback.format_tb(tb)[0]
pymsg = "PYTHON ERRORS:\nTraceback Info:\n" + tbinfo + "\nError Info:\n " + str(sys.exc_type)+ ": " + str(sys.exc_value) + "\n"
AddPrintMessage(pymsg, 2)
msgs = "GP ERRORS:\n" + gp.GetMessages(2) + "\n"
AddPrintMessage(msgs, 2)
####################################################################
##DELETE AN ATTRIBUTE
def delAttr(self,fc,attrname):
gp.deletefield(str(fc),str(attrname))
#keep count
self.NUMATTRS=self.NUMATTRS-1
####################################################################
def listAttrs(self,fcname):
OUTPUT =[]
fieldlist = gp.ListFields(fcname)
fieldlist.reset()
field = fieldlist.next()
while field:
OUTPUT.append(str(field.Name) )
field = fieldlist.next()
if fieldlist:
del fieldlist
if field:
del field
return OUTPUT
####################################################################
def listParts(self,fcname):
OUTPUT =[]
fieldlist = gp.ListFields(fcname)
fieldlist.reset()
field = fieldlist.next()
while field:
OUTPUT.append(str(field.Name) )
field = fieldlist.next()
if fieldlist:
del fieldlist
if field:
del field
return OUTPUT
####################################################################
###LOAD ATTRIBUTES INTO MEMORY
def readAttrs(self,fcname):
self.clearAllInternals()
###
FCOUNT = 0
fields = gp.ListFields(fcname) #sys.argv[1]
fields.reset()
fld = fields.next()
while fld:
self.ATTRNAMES.append( str(fld.Name ) )
self.ATTRTYPES.append( str(fld.Type ) )
fld = fields.next()
FCOUNT=FCOUNT+1
###
if fields:
del fields
if fld:
del fld
self.NUMATTRS = FCOUNT
######################
#MAKE AN ATTR MATRIX BASED ON FIELDS, ACCESS THEM IN ORDER
for ADDFIELD in self.ATTRNAMES:
tempbuffertwo = []
tempbuffer = []
rows=gp.SearchCursor(fcname)
row=rows.Next()
while row:
#if ADDFIELD != 'Shape':
exec ('tempbuffer=row.'+ADDFIELD)
tempbuffertwo.append(tempbuffer)
# tempbuffertwo.append(tempbuffer)
row=rows.Next()
####
if rows:
del rows
if row:
del row
########
self.ATTRVALUES.append(tempbuffertwo)
###SAVE AN ATTRIBUTE TABLE TO A FEATURE
def writeAttrs(self,fcname,field,valuetable):
if self.checkfieldexists(fcname,field)==0:
raise 'ERROR "'+fcname+'" FIELD "'+field +'" DOES NOT EXIST '
########
numattrs = self.countparts(fcname)
numvalues = len(valuetable)
#DEBUG
#print '\n #DEBUG NUMATTRS'
#print numattrs
#print ' #DEBUG NUMVALUES'
#print numvalues
#raw_input()
if self.checkfieldexists(fcname,field):
try:
countaddattr=0
cur = gp.UpdateCursor(fcname,'')
row = cur.Next()
while row:
#row.SetValue('id', 33)
# print 'ERROR writeAttrs EMPTY TABLE INDEXED'
row.SetValue(field, valuetable[countaddattr])
cur.UpdateRow(row)
row = cur.Next()
countaddattr=countaddattr+1
####
if cur:
del cur
if row:
del row
except:
tb = sys.exc_info()[2]
tbinfo = traceback.format_tb(tb)[0]
pymsg = "PYTHON ERRORS:\nTraceback Info:\n" + tbinfo + "\nError Info:\n " + str(sys.exc_type)+ ": " + str(sys.exc_value) + "\n"
AddPrintMessage(pymsg, 2)
msgs = "GP ERRORS:\n" + gp.GetMessages(2) + "\n"
AddPrintMessage(msgs, 2)
####################################################################
###GET AN ATTRIBUTE'S DATA
def getAttrlist(self,fc,attr):
self.clearAllInternals()
##
OUTPUT = []
rows=gp.SearchCursor(fc)
row=rows.Next()
while row:
foo = ''
exec ('foo=row.'+attr)
#print 'FOO '
OUTPUT.append(int(foo)) #DEBUG THIS IS NOT TYPLESS!!
row=rows.Next()
return OUTPUT
#DELETE CURSOR OBJECT TO RELESE LOCKING
if rows:
del rows
if row:
del row
######
def loadAll(self,shapefile):
self.clearAllInternals()
self.readAttrs(shapefile)
############################
###GET GEOMETRY TYPE
def getFieldInfo(self,fc):
self.clearAllInternals()
##
fields = gp.ListFields(fc) #sys.argv[1]
fields.reset()
fld = fields.next()
#self.ATTRVALUES = []
while fld:
print '\n'
print '##FIELD #########################'
print 'Name ' +str(fld.Name )
print 'Editable ' +str(fld.Editable )
print 'Length ' +str(fld.Length )
print 'Type ' +str(fld.Type )
print 'Scale ' +str(fld.Scale )
print 'Domain ' +str(fld.Domain )
self.ATTRNAMES.append(str(fld.Name ))
self.ATTRTYPES.append(str(fld.Type ))
#OTHER
self.Scale.append(str(fld.Scale ))
fld = fields.next()
########
if fields:
del fields
if fld:
del fld
############################
###GET GEOMETRY TYPE
def getGeoInfo(self,fc):
self.clearAllInternals()
desc = gp.Describe(fc)
typeoffeature= str(desc.DataType )
#print 'TYPE IS ' + typeoffeature
##
if typeoffeature == 'RasterDataset':
print '#getGeoInfo RASTER FILE DETECTED, SKIPPING \n'
##
if typeoffeature == 'Tin':
print '#getGeoInfo TIN FILE DETECTED, SKIPPING \n'
##
#if typeoffeature == 'ShapeFile':
# print ' SHAPE FILE DETECTED \n'
##
if typeoffeature == 'ShapeFile' :
rows = gp.SearchCursor(fc)
row = rows.Next()
countparts = 0
countpartswithgeo =0
while row:
feat = row.shape
shapetype= str(feat.Type)
print '\n'
if shapetype == 'polygon':
print '#POLYGON DETECTED '
if shapetype == 'polyline':
print '#LINE DETECTED '
if shapetype == 'point':
print '#POINT DETECTED '
#LOOK AT PARTCOUNT FOR GEOMETRY
checkforgeometry = feat.partCount
#IF PART HAS GEOMETRY
if checkforgeometry !=0:
print '#IS MULTIPART : '+ str(feat.isMultiPart)
print '#PARTCOUNT : '+ str(feat.partCount)
print '#CENTROID : '+ str(feat.centroid)
#NOT ALL FIELDS EXSISTS FOR ALL TYPES
##LINE FIELDS
if shapetype == 'polyline':
print '#LENGTH : '+ str(feat.length)
print '#FIRST POINT : '+ str(feat.firstPoint)
print '#LAST POINT : '+ str(feat.lastPoint)
##POLY FIELDS
if shapetype == 'polygon':
print '#AREA : '+ str(feat.area)
print '#LENGTH : '+ str(feat.length)
print '#FIRST POINT : '+ str(feat.firstPoint)
print '#LAST POINT : '+ str(feat.lastPoint)
##POINT FIELDS
if shapetype == 'point':
print '#FIRST POINT : '+ str(feat.firstPoint)
print '#LAST POINT : '+ str(feat.lastPoint)
##########
countpartswithgeo=countpartswithgeo+1
if checkforgeometry==0:
print 'NO GEOMETRY IN PART ' +str(countparts)
countparts=countparts+1
row = rows.Next()
print '#########################'
print 'TOTAL NUMBER OF PARTS '+str(countparts)
print 'TOTAL NUMBER OF PARTS WITH GEOMETRY '+str(countpartswithgeo)
#DELETE CURSOR OBJECT TO RELESE LOCKING
if rows:
del rows
if row:
del row
############################
###GET COUNT
#first arg is total count(fields) , second is parts with geometry
def countparts(self,fc):
OUTPUT = [] #first arg is total, second is parts with geometry
self.clearAllInternals()
desc = gp.Describe(fc)
typeoffeature= str(desc.DataType )
countparts = 0
##
if typeoffeature == 'ShapeFile' :
rows = gp.SearchCursor(fc)
row = rows.Next()
countpartswithgeo =0
while row:
feat = row.shape
shapetype= str(feat.Type)
checkforgeometry = feat.partCount
if checkforgeometry !=0:
countpartswithgeo=countpartswithgeo+1
##
countparts=countparts+1
row = rows.Next()
#DELETE CURSOR OBJECT TO RELESE LOCKING
if rows:
del rows
if row:
del row
OUTPUT.append(countparts)
OUTPUT.append(countpartswithgeo)
return OUTPUT
###
def gatherCommonAttr(self):
pass
########################################################################
#BEGIN
#foo = ESRI_ATTR_EDIT()
#SHAPEFILE = 'C:/data/Creswell_ForSale_W10.shp'
#DATABASE = 'C:/data/fucker.mdb'
###########################################
#READ ATTRNAMES,ATTRTYPES,AND ALL VALUES , INTO MEMORY FROM A FEATURE CLASS
#foo.readAttrs(SHAPEFILE)
#foo.export_to_data_tree(SHAPEFILE,'C:/reportt.txt')
##
#GET NUM ATTRS (SET FROM READ)
#print foo.NUMATTRS
#SHOW ALL ATTRTYPES
#print foo.ATTRTYPES
#SHOW ATTRNAME BY INDEX
#print foo.ATTRNAMES[3]
#SHOW ATTRVALUES BY INDEX
#print foo.ATTRVALUES[3]
#SHOW ALL FIELDS IN AN ARRAY
#print foo.ATTRNAMES
#print foo.ATTRVALUES
###################################
#TO CLEAR ALL MEMORY (BEFORE LOADING NEXT ATTR)
#foo.clearAllInternals()
###########################################
#ADD ATTR
#foo.addAttr(SHAPEFILE,'butrocker','text')
#foo.addAttr(SHAPEFILE,'ewew','float')
#foo.addAttr(SHAPEFILE,'ewew','long')
#foo.addAttr(SHAPEFILE,'ewew','double')
###########################################
#DELETE AN ATTR
#foo.delAttr(SHAPEFILE,'ewew')
###########################################
#WRITE ATTR
#inserttable = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','m']
#inserttable = [1.3,2.3,3.3,4.3,5.3,6.3,7.3,8.3,9.3,10.3,11.3,12.3,13.3,14.3,15.3]
#inserttable = [12,23,19,22,25,618,76,83,93,103,113,123,133,143,153]
#foo.writeAttrs(SHAPEFILE,'butrocker',inserttable)
###########################################
#GET GEOMETRY INFO
#foo.getGeoInfo(SHAPEFILE)
#####################################
#GET FIELD INFO
#foo.getFieldInfo(SHAPEFILE)
###########################################
#GET AN ATTRIBUTE (VALUE TABLE) BY NAME
#print foo.getFeatureAttr(SHAPEFILE,'NAME')
#GET AN ATTRIBUTE BY NAME AND VALUE ID
#print foo.getFeatureAttrValue(SHAPEFILE,'FID',5)
#GET AN ATTRIBUTE BY PART ?
#foo.getPartAttr(SHAPEFILE)
###########################################
###########################################
###########################################
##MAPLOT STUFF
#objects =['C:data/linez.shp'] #append list of objects
#attrtable =['1803071404700'] #list of numbers
#foo.filter_layers('MAPLOT',attrtable,objects)
#foo.getPartAttr
#foo.getAttrs('C:/data/linez.shp')
<pre>

