The easy solution to set a bookmark inside a Word-document:

require 'win32ole'
word ='Word.Application')
doc = word.Documents.Add("#{path to your template here}")
doc.Bookmarks("bookmark-name").Range.Text = "new content here"

This will work, and will replace the bookmark with the text you wanted to insert.

Recently i had to convert a document that was first built using mail-merge. I am not very familiar with mail-merge, but it seems a specific field can occur multiple times inside the document. This is very convenient. So i looked for a way to replace this behaviour, and still use bookmarks. I know how to set bookmarks programmatically, and this seemed easier than preparing a temporary document first for mail-merging.

My first thought was that i create bookmarks, and give the duplicate bookmarks names like “#{original -bookmark-name}_2” , and inside my program i would go looking if there would be any copies (_2, _3, _4) and set them accordingly. But i looked further. There should be a better way.

Luckily there does exist something called “REF” fields inside Word, which are fields that inherit their content from a certain bookmark! A-ha!
But the above code won’t work, because i actually replace the bookmark with the text, and then nothing is left to be reffered to :)

So the code to set a bookmark turns a bit more complex:

require 'win32ole''Word.Application')

doc = word.Documents.Add("#{your-template-path}")

## wdGoToBookmark = -1, wdCharacter = 1
word.Selection.GoTo("What" => -1, "Name" => "#{your-bookmark-name}")
word.Selection.Delete("Unit" => 1, "Count" => 1)
word.Selection.InsertAfter "#{your-new-text}"
# re-create our bookmark
doc.Bookmarks.Add("Range" => word.Selection.Range, "Name" => "#{your-bookmark-name}")
# update all (referring) fields
# in Word2007, filetype 16 saves as a Word2003 compatible document, 12 is docx, 17 is pdf
doc.SaveAs "#{your-filename}.doc", 16

Actually, although this works, it doesn’t work if two bookmarks are really close, e.g. only seperated by a single space. So the above is not the correct way. Some googling revealed the correct way:

    # new version of code
    bm_name = "#{your-bookmark-name}"
    bm_range = doc.Bookmarks(bm_name).Range
    bm_range.Text = "insert something interesting here"
    doc.Bookmarks.Add bm_name, bm_range

I hope this helps :)