Labeling using ampersand (&) symbol in text via Python

2769
23
Jump to solution
02-02-2023 06:55 AM
PeteJordan
Occasional Contributor III

  I've got a number of different labeling scripts I use and they all at least contain one NAME type field I display.  On the rare occasion, I have names that contain the "&(such as "Rough & Ready").  

  I know the ampersand is a special character and when I use it in my script it starts displaying the other fileds parameters in the output text.

 

Here is an example of one of my simple labeling codes in Python:

def FindLabel([Name_1],[Width_1]):

str_list = []
if [Name_1] not in (None, "<NULL>","<Null>", "", "0"):
str_list.append([Name_1])

if [Width_1] not in (None, "<NULL>","<Null>", "", "0", " ","Varies"):
Width_1_str = '<ITA>Width = {}\'</ITA>'.format("<ITA>" + [Width_1] + "</ITA>")
str_list.append(Width_1_str)

label_str = '\n'.join(str_list)
return(label_str)

 I have found an example using VB and somehow incorporating "&","&amp;" into the script, but I have played around with adding variations of that in my code, but I can't seem to get it to work without errors.

  Any ideas how to simply allow & into my Name_1 field in this example?

Thanks

0 Kudos
1 Solution

Accepted Solutions
RhettZufelt
MVP Frequent Contributor

Whoops, left a relic append in there.  Try the above code now that I have deleted line 28 (str_list.append(name_str)).

R_

View solution in original post

23 Replies
AngelaSchirck
Occasional Contributor II

Are you passing  [Name_1] as a string?

0 Kudos
PeteJordan
Occasional Contributor III

Just what's shown in the code above.  The actual fied is a text field though in the dataset...

 
0 Kudos
RhettZufelt
MVP Frequent Contributor

Not sure your desired output, or input for that matter, but I don't seem to have an issue with the ambersand in a string variable.  You are, however, calling a lot of your "variables" lists.  Python uses the !variable! to define the input variables, not [variable].  Is Width_1 a numeric or text field.  If numeric, putting quotes around the zero's signify that they are text, and if width is number, will still append it if 0.  Also, the .format() was duplicating the <ITA> tags as well.  If that is what you were after, you will have to add that back in.

Try this code, see if it gets you closer to what you are after:

 

 

 

 

def FindLabel([Name_1],[Width_1]):

str_list = []
if [Name_1] not in (None, "<NULL>","<Null>", "", 0):
   str_list.append([Name_1])

if [Width_1] not in (None, "<NULL>","<Null>", "", 0, " ","Varies"):
   Width_1_str = '<ITA>Width = {}\'</ITA>'.format(str([Width_1]))
   str_list.append(Width_1_str)

label_str = '\n'.join(str_list)
return(label_str)

 

 

 

 

RhettZufelt_0-1675362140553.png

 

R_

 

PeteJordan
Occasional Contributor III

  Well first off, the WIDTH is not always a numeric field, it can sometimes be a text field depending on who gives us the data.  This is also one of the simple labeling functions I do, there could be a number of other fields that also get displayed.  I just used these two NAME and WIDTH as an easy example.

  The code you suggested returned an error:

Amp_Error1.jpg

 

Here's an example of what I am experiencing

This is how my names should look and in this case I substituted the '&' with'and'.  It also has the width field shown as well in itallics.

Amp_ex1.jpg

 

Example 2 (amp_ex2.jpg) shows what I am getting if I use the '&' instead... 

Amp_ex2.jpg

0 Kudos
RhettZufelt
MVP Frequent Contributor

It appears as if 2.9.3 won't honor the <ITA> tags, so was getting nowhere.  However, I decided to replace the italics tag with <BOL> tags for testing.

However, according to this page,   "The ampersand (&) and angle bracket (<) are special characters and are not valid in your text if formatting tags are used. Use the equivalent character codes &amp; and &lt; instead.

Annotation

Instead of <ITA>John & Paul</ITA>, use:

<ITA>John &amp; Paul</ITA>

So, will have to look for the special character, and if there, replace with &amp;.

With lines 5 and 6 commented out:

RhettZufelt_0-1675370632990.png

 

Then, uncommented:

RhettZufelt_1-1675370651861.png

Hope this helps figure out what is going on.

R_

 

0 Kudos
PeteJordan
Occasional Contributor III

Ok I got the Name part working with the & which is great and thank you for that.

In the larger code (which is different than the example I showed you), 
I am trying to apply that to 2 fields out of 4.  In this example NAME and ALT_NAME.

I run into issues when trying to do it for a 2nd field. 

Here's the code that I can't seem to get working.  One issue is that you stated the <ITA> and such may not be supported in this fashion, 2nd I can't get this code to work at all regardless of where I place the ALT_NAME1  if statements for the &:

def FindLabel([NAME],[ALT_NAME],[ROUTE],[WIDTH]):
str_list = []

NAME1=[NAME]
ALT_NAME1=[ALT_NAME]
ROUTE1=[ROUTE]
WIDTH1=[WIDTH]
if '&' in NAME1:
NAME1=NAME1.replace("&","&amp;")

if NAME1 not in (None, "<NULL>","<Null>", "", "0"):
str_list.append(NAME1)

if '&' in ALT_NAME1:
ALT_NAME1=ALT_NAME1.replace("&","&amp;")
if ALT_NAME1 not in (None,"<NULL>", "", "0"):
altname_str = "<ITA><FNT size = '6'>({})</FNT></ITA>".format(str([ALT_NAME]))
str_list.append(altname_str)

if ROUTE1 not in (None,"<NULL>", "", "0"):
route_str = "RT#: {}".format([ROUTE])
str_list.append(route_str)

if WIDTH1 not in (None, "<NULL>","<Null>", "", "0", " "):
width_str = "<ITA>Width = {}'</ITA>".format(str([WIDTH]))
str_list.append(width_str)

label_str = '\n'.join(str_list)
return(label_str)




0 Kudos
RhettZufelt
MVP Frequent Contributor

Sorry, my mistake on that error.  I have edited that post, guess still stuck on the ArcMap way of having to actually call that function in the label editor.

 

 

R_

0 Kudos
PeteJordan
Occasional Contributor III

So that at least shortened the script a bit by removing like you said the extra itallics from the WIDTH part, but I still have the same issue with the NAME and using & in the name as in my last screen shot...

0 Kudos
RhettZufelt
MVP Frequent Contributor

For future pasting of code, look at this post, makes it a lot easier to visualize as well as copy/paste.

As far as it not working for ALT_NAME, you are substituting [ALT_NAME] in with the .format, but it is ALT_NAME1  that you did the replace on.  Simple fix.

Also, you said could be text, could be numeric.  Comparing strings with in/not in and None doesn't neccesarily produce consistent results.  I modified this a little to first, see if there is a value in the variable (not Null), then, compare the str(variable) with the not in staments.  Seems to produce the results we're after.

def FindLabel([NAME],[ALT_NAME],[ROUTE],[WIDTH]):
    str_list = []

    NAME1=[NAME]
    ALT_NAME1=[ALT_NAME]
    ROUTE1=[ROUTE]
    WIDTH1=[WIDTH]
    if NAME1:                                        # checks to see if value or Null
        if '&' in NAME1:                             # as string value can print as None, but doesn't work with "not in"
            NAME1=NAME1.replace("&","&amp;")

        if str(NAME1).strip not in ("<NULL>","<Null>","0"):   
            str_list.append(NAME1)
    if ALT_NAME1:
        if '&' in ALT_NAME1:
            ALT_NAME1=ALT_NAME1.replace("&","&amp;")
        if str(ALT_NAME1).strip() not in ("<NULL>","0"):
            altname_str = "<BOL><FNT size = '6'>({})</FNT></BOL>".format(str(ALT_NAME1))
            str_list.append(altname_str)
    if ROUTE1:
        if str(ROUTE1).strip not in ("<NULL>", "0"):
            route_str = "RT#: {}".format(ROUTE1)
            str_list.append(route_str)
    if WIDTH1:
        if str(WIDTH1).strip() not in ("<NULL>","<Null>","0"):
            width_str = "<BOL>Width = {}'</BOL>".format(str(WIDTH1))
            str_list.append(width_str)

    label_str = '\n'.join(str_list)
    return(label_str)

RhettZufelt_0-1675377692234.png

Of course, since my version of Pro doesn't honor the ITA tags, I used BOL to see that it is working.

You will need to replace them if you want italics instead (if it works in your version).

R_