# TEXT_ELEMENT content in map layout not displaying correctly

491
6
12-06-2018 11:54 AM
MVP Regular Contributor

Using ArcMap 10.5.1 and Python 2.7, I have a script that finds a text box in map layout of an MXD(s) by two key words "PRINT DATE" and changes the text to new text. I believe the script is doing what I want it to and it runs with no error. However, the resulting text in the text box is illegible.

Script:

import arcpy, os
from arcpy import env

arcpy.env.workspace = ws = r"path\to\TestFolder"

# format new text
txtBlock = [
'Prepared by the Will County GIS Division',
'302 N Chicago St. Joliet, Il 60432',
'T:(815) 774-6343, E:gis@willcountyillinois.com',
'Print date: <dyn type=\"date\" format=\"\"/>'
]

# create variable that joins lines together with new line character
newTxt = "\n".join(txtBlock)

# list the mxds of the workspace folder
for mxdname in arcpy.ListFiles("*.mxd"):
print "checking document: {}".format(mxdname)
mxd = arcpy.mapping.MapDocument(ws + "\\" + mxdname)

# find textbox by keywords and give it the new text
for elm in arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT"):
if "PRINT DATE" in elm.text.upper():
elm.text = newTxt‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Text box before:

and after:

The following trouble shoots were suggested on my previous post: find text element in MXD with wildcard?

1. I printed out the context of the text box before it was replaced and after using the repr() class:

    for elm in arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT"):
if "PRINT DATE" in elm.text.upper():
print str(elm.text) + "\n"
print "++++++++++++++below is repr+++++++++++++++++++++"
elm.text = newTxt
print repr(elm.text)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Print out:

Prepared by the Will County GIS Division
Print Date: 11.2.2018
302 N. Chicago St. Joliet, Il 60432

++++++++++++++below is repr+++++++++++++++++++++
u'Prepared by the Will County GIS Division\n302 N Chicago St. Joliet, Il 60432\nT:(815) 774-6343, E:gis@willcountyillinois.com\nPrint date: <dyn type="date" format=""/>'‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

2. I ran the MXD through the MXD Doctor and Documet Defragmenter. There was no corrupted element and running the script on a defragmented copy of the MXD made no difference.

3. There were no changes to the font, font size or centering in the Properties of the text box from old to new. As in, the Properties weren't affected.

5. I gave the text box element a name, 'PrintDate'. This didn't seem to have any effect as using the "PRINT DATE" keywords were enough.

    for elm in arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT"):
if "PRINT DATE" in elm.text.upper():
elm.name == 'PrintDate'‍‍‍‍‍‍‍‍‍

6. I know the script works. I tested the script on a new MXD with similar text in a text box. The script ran fine and the resulting new text was displayed correctly! I also had a second text box in the MXD that had the word "date" among the text . I ran the script once with only "DATE" as a key word and it found both text boxes. It knowingly changed both. The odd thing was that while the one I'm after came out illegible again, the second text box was displayed correctly!

I'm wondering if anyone has seen this behaviour before?

Tags (3)
1 Solution

Accepted Solutions
MVP Regular Contributor

The Rectangle Text (in the Drawing toolset) requires a carriage return/line feed pair - at least with Windows.  The text box created with Insert>>Text, only needs a newline but will work with a carriage return/line feed.  So, you just need to insert a \r (carriage return) in front of the \n (newline / line feed).  Here's some sample code.  It may be best to remove carriage returns and split on newlines as there may not always be a carriage return.

for elm in arcpy.mapping.ListLayoutElements(mxd,"TEXT_ELEMENT"):
elm.text = elm.text.replace('\n','\r\n')

# some options in splitting/joining

txtList = elm.text.split('\r\n') # split on CR/LF pair
txtList = (elm.text.replace('\r','')).split('\n') # remove CR and split on newline

elm.text = '\r\n'.join(txtList) # join with CR/LF pair‍‍‍‍‍‍‍‍‍‍‍
6 Replies
MVP Regular Contributor

It appears the text box was created with the Drawing toolset and is "Rectangle Text" as opposed to just Insert >> Text.  I'm not sure if all its properties can be accessed via python, which I believe is part of your goal.

If you resize the text box in an open map, does the text come back into alignment?  Also, if you paste a new version of the text with valid new lines (or just retype the text in the box) then does it come back into alignment?  The idea would be to check is box size is an issue, and if line breaks are an issue.  It also looks like the text may be full justified, as to left or right justified, or centered.

As I haven't experimented much with rectangle text, it might be possible to capture enough properties to do some conversion.  When I get some time, I'll do some experiments.

In the meantime, some documentation that may help: Adding text that flows within a graphic

MVP Regular Contributor

Randy,

Yeah, I think you're right. It seems like the text in question may have been added using the Rectangle Text tool from Drawing. Reason being it has vertices. When text is added to map layout from Insert it looks like this:

I tested what you suggested.

1. After manually resizing the text box in map layout it does not come back into alignment.

2. Here are the properties of the illegible text after running the script:

-After setting the lines manually here and adjusting the textbox a little, it displayed correctly.

Maybe the issue is with the size of this textbox as it is when the script runs. Reason being is because the second textbox I mentioned is the same type as this one, only much bigger (multiple line paragraph). And when this large textbox was replaced (while troubleshooting using only the "DATE" keyword) the newText displayed fine in it.

So, maybe there's a parameter that increases the textbox size that I could use?

MVP Regular Contributor

The Rectangle Text (in the Drawing toolset) requires a carriage return/line feed pair - at least with Windows.  The text box created with Insert>>Text, only needs a newline but will work with a carriage return/line feed.  So, you just need to insert a \r (carriage return) in front of the \n (newline / line feed).  Here's some sample code.  It may be best to remove carriage returns and split on newlines as there may not always be a carriage return.

for elm in arcpy.mapping.ListLayoutElements(mxd,"TEXT_ELEMENT"):
elm.text = elm.text.replace('\n','\r\n')

# some options in splitting/joining

txtList = elm.text.split('\r\n') # split on CR/LF pair
txtList = (elm.text.replace('\r','')).split('\n') # remove CR and split on newline

elm.text = '\r\n'.join(txtList) # join with CR/LF pair‍‍‍‍‍‍‍‍‍‍‍
MVP Regular Contributor

Thanks a lot. It worked nicely. The only thing is the box isn't big enough for the four lines. The dynamic date on the bottom is there only after I stretch the box a tad. I'll have to look into tweaking this somehow.

MVP Regular Contributor

One possibility is to examine the font size property and make it a bit smaller.  You might also be able to tweak the height and width properties. See: TextElement

MVP Regular Contributor

I was able to adjust the font size of the text and also the height of the text box.

    for elm in arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT"):
if "PRINT DATE" in elm.text.upper():
elm.name = 'PrintDate'
if elm.name == 'PrintDate':
elm.fontSize = 5
elm.elementHeight = 0.4871
print "+++date changed+++"‍‍‍‍‍‍‍

Got some help from this post: Change text\ font size element using Arcpy - Geographic Information Systems Stack Exchange