Hi, I am a beginner-novice programmer using Python to build custom tools in ESRI's ArcGIS. I have what seems like a simple problem, but I am afraid I'm missing a core concept. Here goes...

In this simple example I assign string values to some variables and then change the text of a map layout text element using a hard-coded format.

COUNTY = "Tioga"
TOWN = "Wellsboro"
someText.text = COUNTY + " - " + TOWN
# someText would now read:    Tioga - Wellsboro

Now I would like the user to pass a custom format as a parameter.

locTextFormat = arcpy.GetParameterAsText(4)
# what the user passed to locTextFormat: COUNTY + " --- " + TOWN
COUNTY = "Tioga"
TOWN = "Wellsboro"
someText.text = locTextFormat
# now, as expected, someText reads:    COUNTY + " --- " + TOWN
# but, I would like someText to read:      Tioga --- Wellsboro

How do I get python to see the string passed into locTextFormat as two variables concatenated with a string?

I have been digging hard on this one for a couple of days now. I have seen a similar question that was solved using a dictionary (see it here) but although this allows a user to submit different choices, they are still limited by four hard-coded choices. I am looking for my user to enter an unlimited number of valid format strings and get a custom result. It is important to note that the variables COUNTY and TOWN will be assigned values dynamically by looping through several features in a map extent; it is not an option for the user to provide the town/county names at run-time because they will change. An abbreviated version of my final code would look something like:

# I am dynamically getting the town and county name for several features in my map extent and then building a stacked text block to assign to someText 
locTextFormat = arcpy.GetParameterAsText(4)
# what the user passed to locTextFormat: COUNTY + " --- " + TOWN
towns = arcpy.SearchCursor(locLyr)
x = 0
for town in towns:
    TOWN = town.TOWN
    COUNTY = town.COUNTY
    if x == 0:
        locale = locTextFormat
        x += 1
    else:
        locale += '\r' + locTextFormat
        x += 1
someText.text = locale
# again, I realize this code as written is simply building locale with literal strings of the user input; I am looking to have locTextFormat be read as a concatenation of variables and strings

In the code above, if I had three towns/counties in my map extent, I would like to see someText read something like:
Tioga --- Wellsboro
Washington --- Waynesburg
Erie --- Buffalo

Sorry if this was a bit long but I want everyone to know exactly what I am trying to do here. Thanks in advance for any insight you may be able to provide.

Brad

Recommended Answers

All 5 Replies

You can use split() if I understand correctly.

locTextFormat = "COUNTY --- TOWN"
print locTextFormat.split("---")
##
## or is it
COUNTY = "test_county"
TOWN = "test_town"
print COUNTY + " --- " + TOWN
print "%s --- %s" % (COUNTY, TOWN)

You can use split() if I understand correctly.

locTextFormat = "COUNTY --- TOWN"
print locTextFormat.split("---")
##
## or is it
COUNTY = "test_county"
TOWN = "test_town"
print COUNTY + " --- " + TOWN
print "%s --- %s" % (COUNTY, TOWN)

woooee,

Thanks for the tip. I ended up using split to get the components of my user defined input string, and then calling values from a dictionary using the components of the split string. My code is below. This works fine for me, but if anyone has a better/cleaner way of accomplishing this, please let me know. Thanks again!

# Get text format from the user
locTextFormat = arcpy.GetParameterAsText(4)
# The user could have provided:  'COUNTY+ - +TOWN' or 'TOWN+ - +COUNTY' or 'TOWN+ !!! +COUNTY
# The resulting text would read:  'Tioga - Wellsboro' or 'Wellsboro - Tioga' or 'Wellsboro !!! Tioga', respectively.
# Get a reference to the LOCALE layer, select all features that intersect your mapping extent and get a search cursor of those features
    locLyr = arcpy.mapping.ListLayers(mxd, "LOCALE", df1)[0]
    arcpy.SelectLayerByLocation_management(locLyr, "INTERSECT", meLyr)
    towns = arcpy.SearchCursor(locLyr)
# Split the user defined text format into it's components
    listInput = locTextFormat.split("+")
# Loop through the cursor, assign values to the dictionary, extract values from the dictionary using the format stored in listInput, and build the 'locale' text block
    x = 0
    for town in towns:
        TOWN = town.TOWN
        COUNTY = town.COUNTY
        dict={'COUNTY': COUNTY, 'TOWN': TOWN}
        if x == 0:
            locale = dict[listInput[0]]+listInput[1]+dict[listInput[2]]
            x += 1
        else:
            locale += '\r' + dict[listInput[0]]+listInput[1]+dict[listInput[2]]
            x += 1
# Assign text to text element
    localeTextEl.text = locale

You could also use the strings substitution operator %

keywords = set("TOWN COUNTY".split()) # new keywords can be added here

# helper code

import re
word_re = re.compile(r"\b[a-zA-Z]+\b")

def sub_word(match):
    "helper for create_template"
    word = match.group(0)
    return "%%(%s)s" % word if word in keywords else word

def create_template(format):
    "Transform a user format to a template for the % operator"
    format = format.replace("%", "%%")
    return word_re.sub(sub_word, format)

# end of the helper code

user_format = "COUNTY --- TOWN"
template = create_template(user_format)
print "template: ", template
print "example: ", template % dict(TOWN="Wellsboro", COUNTY="tioga")

"""my output -->
template:  %(COUNTY)s --- %(TOWN)s
example:  tioga --- Wellsboro
"""
dict={'COUNTY': COUNTY, 'TOWN': TOWN}

You should print the dictionary as it will only contain one entry. Also, do not use "dict" as a name as that is a reserved word used to convert to a dictionary. Ditto for 'locale' (instead use town_dict, etc. as it then lets the reader know what the dictionary contains).

Thanks for all the suggestions and insight! Take care...

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.