Dynamo to word file?

hey, i know its a stupid thing to ask, bur i want a prefilled word document to fill up project data in its blank spaces (like project name, specific project costs from revit schedule, etc) which i wanna import automatically using dynamo. is that possible?

i cannot find such an option but i know you awesome guys might suggest some solution to this! Thanks in advance.

You could try first exporting to Excel and then to Word using python.

1 Like

yeah @johanboo that might work but it will become two step process, or are you suggesting i should export to excel and then to word using python within dynamo ?

As I recall you can directly read and write rtf files with Dynamo (including formatting), which can be read by word without issue. Just means you have to change from .doc to .rtf.

I used to do the prep work for all my field reports this way. Read the template, last report’s stuff to follow up on, weather on site, and a few other external bits. Then emailed myself the file as Pages on iOS reads that format just as well, and then would add new photos via camera and notes by voice to text as I walked the site. Got back to the office, proof read it and would have it sent out inside an hour.

1 Like

Hello
another solution using Microsoft.Office.Interop.Word

import sys
import clr
import System

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

clr.AddReference("System.Runtime.InteropServices")
import System.Runtime.InteropServices

    
def find_replace(objRng, search_txt, replce_txt):
	missing = System.Type.Missing
	replaceAll = Word.WdReplace.wdReplaceAll
	objRng.Find.Execute(
	search_txt, # search text
	True, # 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?
	replce_txt, # replace with
	replaceAll, # replace enum
	missing, # match Kashida (arabic letters)
	missing, # diatrics?
	missing, # match other Arabic letters
	missing # support right to left
	)
    
def doc_replace_text(source_filename, tokens, values):
	global errors

	word_application = Word.ApplicationClass()
	word_application.visible = True
	document = word_application.Documents.Open(source_filename)
	#Find and Replace Process
	for _find, _replace in zip(tokens,values):
		for myStoryRange  in document.StoryRanges:
			find_replace(myStoryRange , _find, _replace)
			try:
				while myStoryRange.NextStoryRange is not  None:
					q = myStoryRange.NextStoryRange 
					find_replace(q, _find, _replace)
			except:
				import traceback
				errors.append(traceback.format_exc())
			#Find and replace in TextBox(shapes)
			try:	
				for shape in document.Shapes:
					initialText = shape.TextFrame
					if initialText.HasText:
						rangeobj = initialText.TextRange 
						find_replace(rangeobj, _find, _replace)

			except:
				import traceback
				errors.append(traceback.format_exc())
								

filename = IN[0]
tokens = IN[1]
values = IN[2]
errors = []    
word_application = Word.ApplicationClass()
word_application.Quit()
word_application = None
doc_replace_text(filename, tokens, values) 

OUT = errors
13 Likes

wow, this seems like a solution to me :heart_eyes: :heart_eyes:

that is an efficient way, amazing logics :ok_hand:

I am using your code @c.poupin , and it is working fine, except for one thing. When i put a string with more than 255 characters it crash and return an error about the excess of length of the string.
I am trying to solve but i can’t fix it. Anybody know how to solve it? Thanks

Can you post a screenshot of the error? It’s the path’s length of the file?

@c.poupin
Is because the string has more than 255 characters, and I want to write more than 255 characters by string.

The errror: Advertencia: IronPythonEvaluator.Error en la operación EvaluateIronPythonScript.
Traceback (most recent call last):
File “”, line 71, in
File “”, line 43, in doc_replace_text
File “”, line 16, in find_replace
EnvironmentError: System.Runtime.InteropServices.COMException (0x800A16DE): El parámetro de la cadena es demasiado largo.
en Microsoft.Scripting.Interpreter.MethodInfoCallInstruction.InvokeInstance(Object instance, Object args)
en Microsoft.Scripting.Interpreter.DynamicInstructionN.Run(InterpretedFrame frame)
en Microsoft.Scripting.Interpreter.Interpreter.Run(InterpretedFrame frame)
en Microsoft.Scripting.Interpreter.LightLambda.Run4[T0,T1,T2,T3,TRet](T0 arg0, T1 arg1, T2 arg2, T3 arg3)
en IronPython.Compiler.PythonCallTargets.OriginalCallTarget3(PythonFunction function, Object arg0, Object arg1, Object arg2)
en System.Dynamic.UpdateDelegates.UpdateAndExecute5[T0,T1,T2,T3,T4,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
en Microsoft.Scripting.Interpreter.DynamicInstruction6.Run(InterpretedFrame frame) en Microsoft.Scripting.Interpreter.Interpreter.Run(InterpretedFrame frame) en Microsoft.Scripting.Interpreter.LightLambda.Run4[T0,T1,T2,T3,TRet](T0 arg0, T1 arg1, T2 arg2, T3 arg3) en IronPython.Compiler.PythonCallTargets.OriginalCallTarget3(PythonFunction function, Object arg0, Object arg1, Object arg2) en System.Dynamic.UpdateDelegates.UpdateAndExecute5[T0,T1,T2,T3,T4,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4) en Microsoft.Scripting.Interpreter.DynamicInstruction6.Run(InterpretedFrame frame)
en Microsoft.Scripting.Interpreter.Interpreter.Run(InterpretedFrame frame)
en Microsoft.Scripting.Interpreter.LightLambda.Run2[T0,T1,TRet](T0 arg0, T1 arg1)
en IronPython.Compiler.PythonScriptCode.RunWorker(CodeContext ctx)
en Microsoft.Scripting.Hosting.ScriptSource.Execute(ScriptScope scope)
en DSIronPython.IronPythonEvaluator.EvaluateIronPythonScript(String code, IList bindingNames, IList bindingValues)

try this method

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

clr.AddReference("System.Runtime.InteropServices")
import System.Runtime.InteropServices

def find_replace(objRng, search_txt, replce_txt):
	missing = System.Type.Missing
	replaceAll = Word.WdReplace.wdReplaceAll
	if len(replce_txt) < 250:
		objRng.Find.Execute(
		search_txt, # search text
		True, # 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?
		replce_txt, # replace with
		replaceAll, # replace enum
		missing, # match Kashida (arabic letters)
		missing, # diatrics?
		missing, # match other Arabic letters
		missing # support right to left
		)
	else:
		i =0
		flag = True
		while flag and i < 20: # prevent infiniteloop
			copyRange = objRng.Duplicate 
			flag = copyRange.Find.Execute(
			search_txt, # search text
			missing, # match case
			missing, # match whole word
			missing, # match wildcards
			missing, # match sounds like
			missing, # match all word forms
			missing, # forward?
			missing, # wrap enum
			missing, # format?
			missing, # replace with
			missing, # replace enum
			missing, # match Kashida (arabic letters)
			missing, # diatrics?
			missing, # match other Arabic letters
			missing # support right to left
			)
			if not flag:
				break
			else:
				copyRange.Text = replce_txt
			i += 1
	  
def doc_replace_text(source_filename, tokens, values):
	global errors
	word_application = Word.ApplicationClass()
	word_application.visible = True
	document = word_application.Documents.Open(source_filename)
	#time.sleep(2)
	#Find and Replace Process
	for _find, _replace in zip(tokens,values):
		for myStoryRange  in document.StoryRanges:
			find_replace(myStoryRange , _find, _replace)
			try:
				while myStoryRange.NextStoryRange is not  None:
					q = myStoryRange.NextStoryRange 
					find_replace(q, _find, _replace)
			except:
				import traceback
				errors.append(traceback.format_exc())
			#Find and replace in TextBox(shapes)
			try:	
				for shape in document.Shapes:
					initialText = shape.TextFrame
					if initialText.HasText:
						rangeobj = initialText.TextRange 
						find_replace(rangeobj, _find, _replace)

			except:
				import traceback
				errors.append(traceback.format_exc())
								

filename = IN[0]
tokens = IN[1]
values = IN[2]
errors = []    
word_application = Word.ApplicationClass()
word_application.Quit()
word_application = None
doc_replace_text(filename, tokens, values) 

OUT = errors
4 Likes

Perfect. Working. Great the loop inside de function! :slight_smile:

1 Like

@c.poupin a query if I wanted to edit more than a single word how could I do it, what am I doing wrong

Hello @Christhian
try like this with this code

1 Like

As always thank you very much, sometimes the solution is simple.

1 Like

@c.poupin I apologize that there will not be a new thread for this question but if I wanted to change several words at the same time, would it be this way?

just add a for loop

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

clr.AddReference("System.Runtime.InteropServices")
import System.Runtime.InteropServices

def find_replace(objRng, search_txt, replce_txt):
	missing = System.Type.Missing
	replaceAll = Word.WdReplace.wdReplaceAll
	if len(replce_txt) < 250:
		objRng.Find.Execute(
		search_txt, # search text
		True, # 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?
		replce_txt, # replace with
		replaceAll, # replace enum
		missing, # match Kashida (arabic letters)
		missing, # diatrics?
		missing, # match other Arabic letters
		missing # support right to left
		)
	else:
		i =0
		flag = True
		while flag and i < 20: # prevent infiniteloop
			copyRange = objRng.Duplicate 
			flag = copyRange.Find.Execute(
			search_txt, # search text
			missing, # match case
			missing, # match whole word
			missing, # match wildcards
			missing, # match sounds like
			missing, # match all word forms
			missing, # forward?
			missing, # wrap enum
			missing, # format?
			missing, # replace with
			missing, # replace enum
			missing, # match Kashida (arabic letters)
			missing, # diatrics?
			missing, # match other Arabic letters
			missing # support right to left
			)
			if not flag:
				break
			else:
				copyRange.Text = replce_txt
			i += 1
	  
def doc_replace_text(source_filename, tokens, values):
	global errors
	word_application = Word.ApplicationClass()
	word_application.visible = True
	document = word_application.Documents.Open(source_filename)
	#time.sleep(2)
	#Find and Replace Process
	for _find, _replace in zip(tokens,values):
		for myStoryRange  in document.StoryRanges:
			find_replace(myStoryRange , _find, _replace)
			try:
				while myStoryRange.NextStoryRange is not  None:
					q = myStoryRange.NextStoryRange 
					find_replace(q, _find, _replace)
			except:
				import traceback
				errors.append(traceback.format_exc())
			#Find and replace in TextBox(shapes)
			try:	
				for shape in document.Shapes:
					initialText = shape.TextFrame
					if initialText.HasText:
						rangeobj = initialText.TextRange 
						find_replace(rangeobj, _find, _replace)

			except:
				import traceback
				errors.append(traceback.format_exc())
								
toList = lambda x : x if hasattr(x, '__iter__') else [x]
lst_filenames = toList(IN[0])
tokens = IN[1]
values = IN[2]
errors = []    
word_application = Word.ApplicationClass()
word_application.Quit()
word_application = None
for filename in lst_filenames:
	doc_replace_text(filename, tokens, values) 

OUT = errors
1 Like

As always thank you very much @c.poupin , you make it look so simple