Replace Word text using Interop

Hello,

I am trying to do something pretty complicated so any help is appreciated.
Basically I have a word document which I use as a template. I would like to use the Microsoft.Office.Interop.Word API to replace text within that document with information from the current Revit document.

I’ve seen this IronPython post and would like to use it in a Python node: http://www.ironpython.info/index.php?title=Replace_Text_within_a_Word_document

Here’s my code so far:

#Some code taken from https://gist.github.com/ejstembler/1049552
import clr
import sys
import System

clr.AddReference("Microsoft.Office.Interop.Word")
import Microsoft.Office.Interop.Word as Word

def doc_replace_text(source_filename, tokens, values, destination_filename):
	
	missing = System.Type.Missing
	replaceAll = Word.Wd.Replace.wdReplaceAll
	
	word_application = Word.ApplicationClass()
	word_application.visible = False
	
	document = word_application.Documents.Open(source_filename)
	
	for i in range(len(tokens)):
		for r in document.StoryRanges:
			#print "i = %d, tokens[i] = %s, values[i] = %s" % (i, tokens[i], values[i])
			r.Find.Text = tokens[i]
			r.Find.Replacement.Text = values[i]
			r.Find.Wrap = Word.WdFindWrap.wdFindContinue
			r.Find.Execute(missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, replaceAll, missing, missing, missing, missing)
	
	time.sleep(3)
	document.SaveAs(destination_filename)
	document.Close()
	document = None
	
	word_application.Quit()
	word_application = None

#The inputs to this node will be stored as a list in the IN variables.

file_name = IN[0]
search_terms = IN[1]
replace_terms = IN[2]
destination_name = IN[3]

doc_replace_text(file_name, search_terms, replace_terms, destination_name)

#Assign your output to the OUT variable.
OUT = 0

The Python node crashes and says this:
Warning: IronPythonEvaluator.EvaluateIronPythonScript operation failed.
Traceback (most recent call last):
File “”, line 49, in
File “”, line 13, in doc_replace_text
AttributeError: attribute ‘Wd’ of ‘namespace#’ object is read-only

If anyone could help me with this, that would be great.
Still new to all this so please excuse confusion I’m sure to have. :stuck_out_tongue:

Thanks!

3 Likes

I figured out how to do this! I will update the thread soon with a solution.

2 Likes

Hello all,

Here’s the update on that code I was writing before. The problem above wasn’t the only road block I ran into so I decided to figure it all out before posting so I wasn’t just talking to myself. :smiley:

I will eventually make this into a .dyf so it can be used for other documents and makes more sense to people who don’t know how to use it. You’ll have to see if I make it public or not, still deciding. :stuck_out_tongue:

A special thanks to https://gist.github.com/ejstembler/1049552 and https://github.com/allevaton because I would’ve been completely lost in writing this without them. Also thanks to @jacob.small for help in figuring out a gameplan and guidance!

Last thing, if there’s any advice or edits you’d like to write as a reply, I’m more than happy to hear it!
Thanks!

# Written by Lynn Quagliato, https://forum.dynamobim.com/u/quagliatol/summary
# Some code taken from https://gist.github.com/ejstembler/1049552
# Made with help from https://github.com/allevaton

# Imports

import clr
import sys
import System

clr.AddReference("Microsoft.Office.Interop.Word")
import Microsoft.Office.Interop.Word as Word

# Code

def doc_replace_text(source_filename, tokens, values, destination_filename):
	
	missing = System.Type.Missing
	replaceAll = Word.WdReplace.wdReplaceAll
	
	word_application = Word.ApplicationClass()
	word_application.visible = False
	
	document = word_application.Documents.Open(source_filename, missing, True)
	
	for i in range(len(tokens)):
		for r in document.StoryRanges:
			r.Find.Execute(
			tokens[i], # search text
			missing, # match case
			missing, # match whole word
			missing, # match wildcards
			missing, # match sounds like
			missing, # match all word forms
			True, # forward?
			Word.WdFindWrap.wdFindContinue, # wrap enum
			missing, # format?
			values[i], # replace with
			replaceAll, # replace enum
			missing, # match Kashida (arabic letters)
			missing, # diatrics?
			missing, # match other Arabic letters
			missing # support right to left
			)
	
	document.SaveAs(destination_filename)
	document.Close()
	document = None
	
	word_application.Quit()
	word_application = None

# Inputs and function

file_name = IN[0]
search_terms = IN[1]
replace_terms = IN[2]
destination_name = IN[3]

doc_replace_text(file_name, search_terms, replace_terms, destination_name)

# Assign your output to the OUT variable.

OUT = 1

PS. Yes, output is 1 no matter what because I’m still learning and working on this. lol

6 Likes

In the end, the node looks something like this:
Word dyf

4 Likes

Awesome work! Really glad to see this is being exposed!

For some reason I’m having trouble making this work on a network. It works for me, but when another user uses it on a shared network location it doesn’t work, even if it’s the exact same code.

I’ve added this to the code too:
sys.path.append(r’C:\Program Files (x86)\IronPython 2.7\Lib’)

Anyone have any thoughts or ideas? Really stuck here.
Running the exact same code on 2 computers and it’s not working. Wondering if anyone else has experienced this.

Try running it as the source python instead of a custom node.

1 Like

Ah. The whole time the other users didn’t have their networks mapped properly. The script runs correctly. :smiley:

1 Like

Hi All I have text notes In all the sheets and I have around 250 sheets and I want to select all this notes only not the other notes in the project and delete them any help thanks

Hi @mahmoud.radwanVLQUU, it sounds like you’re trying to get text on Revit sheets. This thread was made so you can work with text in a Word document.
Sorry for the confusion!
It might make more sense to make a new thread about what you’re trying to do. Thanks!

1 Like

Wil it work if i want to insert images or an excel table in a doc file?
Thank you!

1 Like