Thursday, 6 August 2015

arcpy - How to keep a parameter blank in a script tool?


SCRIPT TOOL IMAGE


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:


Tool setup showing optional parameter


and the results:


results of the tool


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

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...