setting word bookmarks from ruby

The easy solution to set a bookmark inside a Word-document: [ruby] require 'win32ole' word = WIN32OLE.new('Word.Application') doc = word.Documents.Add("#{path to your template here}") doc.Bookmarks("bookmark-name").Range.Text = "new content here" [/ruby] 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: [ruby] require 'win32ole' word=WIN32OLE.new('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 doc.Fields.Update # in Word2007, filetype 16 saves as a Word2003 compatible document, 12 is docx, 17 is pdf doc.SaveAs "#{your-filename}.doc", 16 [/ruby] [UPDATE] 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: [ruby] # 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 [/ruby] I hope this helps :)


Comments
Add comment

Recent comments

Tags

ruby on rails 34 ruby 26 rails3 17 rails 15 oracle 11 rspec 9 rspec2 7 jquery 7 ubuntu 5 javascript 5 windows 5 activerecord 3 refactoring 3 geoserver 3 gis 3 arrrrcamp 3 actionmailer 2 oracle spatial 2 tdd 2 postgis 2 routing 2 rvm 2 mongoid 2 csharp 2 thin 2 win32 2 gem 2 rails4 2 git 2 service 2 haml 2 cucumber 2 view testing 2 i18n 1 displaysleep 1 spatial 1 gemsets 1 wubi 1 oracle_enhanced_adapter 1 migrations 1 watchr 1 ci 1 plugins 1 coderetreat 1 ie8 1 ssl 1 oci 1 nested model form 1 wcf 1 11.04 1 jsonp 1 ruby-oci8 1 teamcity 1 engines 1 pgadmin 1 soap 1 content_for 1 word automation 1 plugin 1 capybara 1 xml 1 bootstrap 1 migrate to rails3 1 mvc 1 unity 1 rendering 1 word2007 1 x64 1 limited stock 1 fast tests 1 pl/sql 1 delayed_job 1 pdf 1 test coverage 1 optimization 1 processing 1 borland 1 method_missing 1 cross-browser 1 devise 1 schema_plus 1 mongo 1 mongrel 1 dual boot 1 usability 1 mongrel_service 1 dba 1 mission statement 1 model 1 metadata 1 rcov 1 exceptions 1 image_tag 1 attachments 1 bde 1 css 1 yield 1 ajax 1 generative art 1 rails-assets 1 coordinate systems 1 submodules 1 netzke 1 ora-01031 1 authlogic 1 postgresql 1 shopping cart 1 agile 1 fast_tagger 1 subjective 1 wice_grid 1 generators 1 nvidia 1 mongodb 1 etsyhacks 1 staleobjecterror 1 session 1 jeweler 1 wordpress hacked 1 jasmine 1 heroku 1 rjs 1 life 1 unobtrusive-javascript 1 render_anywhere 1 html5 1 rails31 1 json 1 cocoon 1 mingw32 1 observe_field 1 osx 1 actionwebservice 1 testing 1 debugging 1 strings 1