Hello!
I'm currently trying to create a button within arcmap that runs a set of if-then rules to fill in a blank field within the layer's attribute table. I've been able to do this in the field calculator with no problem, but in order to speed up the process, I would like to be able to run the process in one click rather than manually labeling.
My issue is that I don't know how to get it so that the button takes the already selected features and then proceeds to run the nested statements.
import arcpy
import pythonaddins
class BlockAnno(object):
"""Implementation for Test_addin.button (Button)"""
def __init__(self):
self.enabled = True
self.checked = False
def onClick(self):
lyr = pythonaddins.GetSelectedTOCLayerOrDataFrame()
with arcpy.da.UpdateCursor(lyr,["block", "sub_code"]) as blockanno:
if sub_code != '0000':
if sub_code != '0780':
if block[0:3].isdigit():
blockanno = str(block[0:3].lstrip('0'))
elif block[2].isalpha():
if block[0:2] == '00':
blockanno = str(block[0:].strip('0'))
cursor.updateRow()
return(BlockAnno)
I'm hoping this is feasible, but would appreciate any guidance or advice.
Solved! Go to Solution.
Edited to fix indexes.
First look at it, I think you are missing some things for the cursor. It looks like you are missing the iteration part:
for row in blockanno:
if row[1] != '0000' and row[1] != '0780':
...
and
cursor.updateRow()
should be
blockanno.updateRow(row)
You need to include the field that you are updating. As written, blockanno is the cursor object, so include the field that you want to update after the "sub_code" in the list of fields there so its index is row[2].
row[2] = str(row[0:].strip('0'))
Hopefully this will get you going.
Edited to fix indexes.
First look at it, I think you are missing some things for the cursor. It looks like you are missing the iteration part:
for row in blockanno:
if row[1] != '0000' and row[1] != '0780':
...
and
cursor.updateRow()
should be
blockanno.updateRow(row)
You need to include the field that you are updating. As written, blockanno is the cursor object, so include the field that you want to update after the "sub_code" in the list of fields there so its index is row[2].
row[2] = str(row[0:].strip('0'))
Hopefully this will get you going.
And you need to indent the .updateRow(row) to be within the ' with arcpy.da.UpdateCursor() ' call.
Thank you! That definitely changed my button from it's missing state. Unfortunately, however, even after the alterations to the script, it will not change those null values from the blockanno column to a product following the nested statements. Any thoughts? I suspect it's stemming from trying to grab the manually grabbed selected features, because if I run that function in the python window of my project, lyr comes up with "none".
import arcpy
import pythonaddins
class ButtonClass1(object):
"""Implementation for Test2_addin.button (Button)"""
def __init__(self):
self.enabled = True
self.checked = False
def onClick(self):
## if editing:
## elif msg -- put on edit and then exit
lyr = pythonaddins.GetSelectedTOCLayerOrDataFrame()
with arcpy.da.UpdateCursor(lyr,["block", "sub_code", "blockanno"]) as blockanno:
for row in blockanno:
if row[1] != '0000' and row[1] != '0780':
if row[0][0:3].isdigit():
row[2] = str(row[0:3].lstrip('0'))
elif row[0].isalpha():
if row[0][0:2] == '00':
row[2] = str(row[0:].strip('0'))
blockanno.updateRow(row)
Looking at the lines where you are assigning values to row[2], it looks like you are not selecting specific row index to slice. you will need to reference that index position
row[2] = str(row[0][0:3].lstrip('0'))
and
row[2] = str(row[0][0:].strip('0'))
if you wanted to concatenate row index 0 and 1, you'll have to add each row index like
row[2] = f'{row[0]}{row[1]}'.lstrip('0')
and
row[2] = f'{row[0]}{row[1]}'.strip('0')