DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world
Microsoft Word Document Merge Done With Ruby And Office Automation
This is basic Microsoft Word merge program. You can probably get it done a lot easier with Word
build in merge function with small difference. This program can also merge different
pictures on different pages.
Whole idea is to make a template documents with variable parts written as names
surrounded by square brackets [name] [company] [whatever]. Program creates work
document and replaces every occurring of [whatever] with values supplied as parameter.
At the end work document is copied to resulting document, cleared and prepared for
another round.
require 'win32ole'
###############################################################
# hash_data: Data is passed as array of hashes, where each element of array holds
# data to be used on resulting page. 'name' => 'my Name', 'company' => 'Some company' etc...
###############################################################
def word_merge(hash_data)
begin
#word.Visible = true
path = fso.GetAbsolutePathName('my_template.doc')
doc = word.Documents.Open(path)
resdoc = word.Documents.Add
work = word.Documents.Add
hash_data.each do |r|
# define some dynamic data prior to put it on document
r['date'] = date_with_words(Time.now)
# Clear work document
work.ActiveWindow.Selection.WholeStory
work.ActiveWindow.Selection.Delete
# Select everything in source document
doc.ActiveWindow.Selection.WholeStory
doc.ActiveWindow.Selection.Copy
# Paste to work document
work.ActiveWindow.Selection.Paste
work.ActiveWindow.Selection.WholeStory
# Initialize find
find = word.Selection.Find
# for each key in hash table
r.each do |key, value|
# Go to top of document
word.Selection.HomeKey('unit' => 6)
# find text
find.Text = "[#{key}]"
# replace all
while word.Selection.Find.Execute
word.Selection.TypeText('text' => value)
end
end
# picture is a variable of some id
pic_name = "images/pic#{r[pic_id]}.bmp"
if File.exist?(pic_name)
path = fso.GetAbsolutePathName(pic_name)
# determine paragraph to which picture will be put relative to
shape_canvas = work.Shapes.AddCanvas(10,65,101,51, work.Paragraphs(24).Range )
# add picture to canvas
shape_canvas.CanvasItems.AddPicture('FileName' => path, 'LinkToFile' => true, 'SaveWithDocument' => false, 'Left' => 1, 'Top' => 1, 'Width' => 100, 'Height' => 50)
end
# Document is ready. Select everything in work document
work.ActiveWindow.Selection.WholeStory
work.ActiveWindow.Selection.Copy
# Paste to resulting doc
word.Selection.EndKey('unit' => 6)
resdoc.ActiveWindow.Selection.Paste
end
# save to pdf
path = fso.GetAbsolutePathName('result.pdf')
resdoc.SaveAs(path, 17)
# Since this is mostly done in batch, some reporting on errors is essential.
rescue Exception => exc
text = ''
exc.backtrace.each {|c| text << c + "\n" }
text << exc.message
File.open('trace.log','w+') { |f| f.write text }
end
# Clear everything behind
resdoc.close('SaveChanges' => 0) unless resdoc.nil?
doc.close('SaveChanges' => 0) unless doc.nil?
work.close('SaveChanges' => 0) unless work.nil?
word.quit
end





