I've developed a sort of find and replace script tool that functions. But I'm not able to figure out how to find empty cells in fields and replace them.For the "Find" parameter, I have tried entering "", '', None, null, and < null >.
An example that might make this clearer. Say you had a field in a table with every row empty, and you wanted to make them say "Not Available" or something instead, which you would enter in the "replace" parameter.
I feel like this is a tool/syntax issue and not really a script one, no?
import arcpy
FC = arcpy.GetParameterAsText(0)
oldText = arcpy.GetParameterAsText(1)
replaceText = arcpy.GetParameterAsText(2)
targetField = arcpy.GetParameterAsText(3)
queryString = targetField + ' = ' + "'" + oldText + "'"
try:
with arcpy.da.UpdateCursor(FC, (targetField), queryString) as cursor:
for row in cursor:
if row[0] == oldText:
row[0] = replaceText
cursor.updateRow(row)
arcpy.AddMessage("String where " + queryString + " found and replaced with " + replaceText)
except:
arcpy.AddMessage(arcpy.GetMessages())
arcpy.AddError("Failed to find and replace where " + queryString)
Answer
Expanding on the comments:
import sys, arcpy
FC = arcpy.GetParameterAsText(0)
oldText = arcpy.GetParameterAsText(1)
replaceText = arcpy.GetParameterAsText(2)
targetField = arcpy.GetParameterAsText(3)
if len(replaceText) == 0:
replaceNone = True
else:
replaceNone = False
try:
if replaceNone:
d = arcpy.Describe(FC)
# branch for each database type
if d.dataType == "ShapeFile":
queryString = targetField + ' = \'\'' # empty string '' or not at all
with arcpy.da.UpdateCursor(FC, (targetField), queryString) as cursor:
for row in cursor:
if len(row[0].replace(" ","")) == 0:
row[0] = replaceText
cursor.updateRow(row)
arcpy.AddMessage("String where none found replaced with {0}".format(replaceText))
elif d.dataType == "FeatureClass":
queryString = targetField + ' is null'
with arcpy.da.UpdateCursor(FC, (targetField), queryString) as cursor:
for row in cursor:
row[0] = replaceText # go ahead and replace the null fields as decided by the cursor
cursor.updateRow(row)
arcpy.AddMessage("String where none found replaced with {0}".format(replaceText))
else:
arcpy.AddError("Unknown feature type")
sys.exit(-1)
else:
# any string that is not None
queryString = targetField + ' = ' + "'" + oldText + "'"
with arcpy.da.UpdateCursor(FC, (targetField), queryString) as cursor:
for row in cursor:
if row[0] == oldText:
row[0] = replaceText
cursor.updateRow(row)
arcpy.AddMessage("String where " + queryString + " found and replaced with " + replaceText)
except:
arcpy.AddMessage(arcpy.GetMessages())
arcpy.AddError("Failed to find and replace where " + queryString)
Because of the different handling of empty/null cells between databases and actual values it's necessary to branch early. Different query strings are needed for null values and, as I have said on your previous post, the whereclause can be omitted as it would just confuse the issue. It's better to test for empty/whitespace strings with len(
and replace(" ","")
operators to clear out just space strings but to leave any genuine strings... also replace(" ","").replace("\t","")
might be a good idea but I haven't seen many fields filled with tab
in a while so (being lazy) I skip it; I'm sure that will come back to bite me one day.
To put to rest (conclusively) the value of an optional string argument I created a simple script:
import arcpy
Par = arcpy.GetParameterAsText(0)
if Par == None:
arcpy.AddMessage("Parameter is none")
else:
if len(Par) == 0:
arcpy.AddMessage("Parameter is 0 length string")
else:
arcpy.AddMessage("Parameter is {0}".format(Par))
Setup like this:
and the results:
So it turns out that an optional unfilled string is a 0 length string, not None
or '#'
, which changes the line if replaceText == None:
to if len(replaceText) == 0:
to test if the replaceText parameter of the tool is blank - insinuating Null, in the case where the replaceText is blank Null values in databases and empty/whitespace strings in shapefiles will be replaced. Note that this only works for strings... different strategies need to be employed with numeric and date fields, but that is a separate question by itself.
No comments:
Post a Comment