importdocxdefdocx_find_replace_text(doc,search_text,replace_text):paragraphs=list(doc.paragraphs)fortindoc.tables:forrowint.rows:forcellinrow.cells:forparagraphincell.paragraphs:paragraphs.append(paragraph)forpinparagraphs:ifsearch_textinp.text:inline=p.runs# Replace strings and retain the same style.# The text to be replaced can be split over several runs so# search through, identify which runs need to have text replaced# then replace the text in those identifiedstarted=Falsesearch_index=0# found_runs is a list of (inline index, index of match, length of match)found_runs=list()found_all=Falsereplace_done=Falseforiinrange(len(inline)):# case 1: found in single run so short circuit the replaceifsearch_textininline[i].textandnotstarted:found_runs.append((i,inline[i].text.find(search_text),len(search_text)))text=inline[i].text.replace(search_text,str(replace_text))inline[i].text=text
replace_done=Truefound_all=Truebreakifsearch_text[search_index]notininline[i].textandnotstarted:# keep looking ...continue# case 2: search for partial text, find first runifsearch_text[search_index]ininline[i].textandinline[i].text[-1]insearch_textandnotstarted:# check sequencestart_index=inline[i].text.find(search_text[search_index])check_length=len(inline[i].text)fortext_indexinrange(start_index,check_length):ifinline[i].text[text_index]!=search_text[search_index]:# no match so must be false positivebreakifsearch_index==0:started=Truechars_found=check_length-start_index
search_index+=chars_found
found_runs.append((i,start_index,chars_found))ifsearch_index!=len(search_text):continueelse:# found all chars in search_textfound_all=Truebreak# case 2: search for partial text, find subsequent runifsearch_text[search_index]ininline[i].textandstartedandnotfound_all:# check sequencechars_found=0check_length=len(inline[i].text)fortext_indexinrange(0,check_length):ifinline[i].text[text_index]==search_text[search_index]:search_index+=1chars_found+=1else:break# no match so must be endfound_runs.append((i,0,chars_found))ifsearch_index==len(search_text):found_all=Truebreakiffound_allandnotreplace_done:fori,iteminenumerate(found_runs):index,start,length=[tfortinitem]ifi==0:text=inline[index].text.replace(inline[index].text[start:start+length],str(replace_text))inline[index].text=textelse:text=inline[index].text.replace(inline[index].text[start:start+length],'')inline[index].text=text# print(p.text)# sample usage as per exampledoc=docx.Document('find_replace_test_document.docx')docx_find_replace_text(doc,'Testing1','Test ')docx_find_replace_text(doc,'Testing2','Test ')docx_find_replace_text(doc,'rest','TEST')doc.save('find_replace_test_result.docx')