find text element in MXD with wildcard?

2863
28
Jump to solution
11-13-2018 02:16 PM
JaredPilbeam2
MVP Regular Contributor

I have a working script that searches for a text element in an MXD and replaces it with new text. I'm using it to update the "print date: mo./day/year". But, this method is sort of limited in that it only finds that exact string. In my map document folder, the dates of these maps differ from each other. So, how can I make the script replace an open-ended string? 

I've tried:

oldText = "Print Date: "

and

oldText = "Print Date: *"

As the script is here, "oldText = Print Date: 9.6.2016" will be replaced with "newText = Print Date: 11/13/2018". But, dates on other maps could be anything. If I could replace the old with dynamic text date that would be even better.

arcpy.env.workspace = Workspace = r"path\to\TestFolder"
Output = r"path\to\TestFolder2"
oldText = "Print Date: 9.6.2016"
oldList = oldText.split(', ')
newText = "Print Date: 11/13/2018"
newList = newText.split(', ')

# list the mxds of the workspace folder
for mxdname in arcpy.ListFiles("*.mxd"):
    print "checking document: {}".format(mxdname)
# set the variable
    mxd = arcpy.mapping.MapDocument(Workspace + "\\" + mxdname)
# replace elements that occur in the map document
    for elm in arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT"):
        counter = 0
        for text in oldList:
            if text in elm.text:
                elm.text = elm.text.replace(text, newList[counter])
                print '{} changed'.format(elm.text)
                counter = counter + 1
            else:
                counter = counter + 1

    for elm in arcpy.mapping.ListLayoutElements(mxd, ""):
        counter = 0
        for text in oldList:
            if text in mxd.title:
                mxd.title = elm.text.replace(text, newList[counter])
                counter = counter + 1
            else:
                counter = counter + 1
# move the mxd.saveACopy outside of the if loop so a copy is saved even it does not meet the condition of the if loops
    mxd.save() #(os.path.join(Output + "\\" + mxdname))
# do not include this delete statement inside the above loop or it will delete the mxd object inside the loop. Make sure to dedent.
del mxd‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
28 Replies
DanPatterson_Retired
MVP Emeritus

Arthur Conan Doyle Quotes. Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth.

RandyBurton
MVP Alum

I noticed a couple of utilities in the ArcGIS directory that may help if a map file has become corrupted.  I would save a backup copy first.

Using the MXD Doctor utility and Using the Document Defragmenter utility

JaredPilbeam2
MVP Regular Contributor

Randy,

Thanks. The MXD Doctor did not find a single issue. I then ran the Defragmenter, which saved a copy of the MXD. It shrunk the size, of course. And then I ran the script on the defragmented copy of the MXD and there was no difference in output. After trying yours and Curtis' ideas leads me to believe it may not be a corrupt MXD.

On top of that, there's a separate text box in the MXD that also has the word "date". I haven't mentioned it because I figured I'd straighten that problem out after figuring out my initial problem of changing the date in the "Prepared by..." text box. Anyways, this second text box was also found by the script and the text was changed to the new text. And it wasn't befuddled at all? As in, it was clear and legible.

0 Kudos
curtvprice
MVP Esteemed Contributor

I suggest some debugging, print out the context of the textbox pre-corruption (ie before your search/replace) and after, like this: print(repr(text)) -- this will sort of whether you need a different flavor of line delimeters to get it to work. 

JaredPilbeam2
MVP Regular Contributor

Curtis,

Thanks. I did that. And to my not-so-experienced eyes I don't see anything odd. 

Code:

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=\"\"/>'
]
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)

    for elm in arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT"):
        if " 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=""/>'

In the map, the text box still goes from this:

to this:

0 Kudos
DanPatterson_Retired
MVP Emeritus
oldText = "Print Date: 9.6.2016"

newdate = "12.12.2018"

if "PRINT DATE" in oldText.upper():
    print("{} {}".format(oldText.split(":")[0], newdate))
    
Print Date 12.12.2018
RandyBurton
MVP Alum

Just curious, what version of ArcMap are you using?  I notice your properties box has a few more tabs: Columns and Margins, Area, and Frame.

0 Kudos
JaredPilbeam2
MVP Regular Contributor

It's ArcMap 10.5.1

0 Kudos
JaredPilbeam2
MVP Regular Contributor
0 Kudos