VSTO - fun with Word Templates
I have been getting very excited about VSTO. As soon as I started playing I realised that I'd be able to create a template project and have code that could fill in some of the fields such as names and addresses based on the XML nodes it finds in the template.
I decided that I could have one, very generic .Net assembly that fills-in fields within the document based on their names. I could then hook-up multiple word templates to that assembly simply by making sure that the document template has the '_AssemblyLocation0' and '_AssemblyName0' custom properties mapping to the assembly in question. The beauty of this is that a non-developer could do the same as long as then followed the agreed naming convention for the XML nodes within the document.
The challenge now was to have code that ran when opening a new document based on the template, but then 'un-hooking' the code from the resulting document so that it was just an ordinary letter or fax again. The answer was to delete the custom document properties as follows (I also show how I added some new custom document properties).
ThisDocument.CustomDocumentProperties("_AssemblyLocation0").Delete()
ThisDocument.CustomDocumentProperties("_AssemblyName0").Delete()
With ThisDocument.CustomDocumentProperties
.Add("NameID", False, Office.MsoDocProperties.msoPropertyTypeNumber, 14543)
.Add("ClientCode", False, Office.MsoDocProperties.msoPropertyTypeString, "GS1564")
.Add("AutoGeneratedDate", False, Office.MsoDocProperties.msoPropertyTypeDate, Now())
End With
[UPDATE - I have since found some info on the SetAssemblyNameAndLocation method, which you can use to set assembly links from an admin script]
I came across a couple of things that had me stuck though, which I thought might be worth blogging about:
I was totally stuck wondering why code I had put into a document template project didnt run when word created a new document based on that template.
In the meantime I used Matt Reynolds' fantastic newsgroup aggregator to have a search on the VSTO newsgroup:
http://www.dotnet247.com/247reference/msgs/47/237749.aspx
And I found this:
"The reason the document does not execute the assembly is that the property _AssemblyLocation0 references a relative location. When the document or the template itself is moved to a different location, the assembly cannot be found any more.
The easy workaround is to edit this property and make it an absolute location instead. It is easy to do that by hand by going to the menu File/Properties/Custom. It can also be done at runtime. One of the VSTO Word samples does exactly that in method MakeAbsoluteAssemblyLocation."
Which I think also makes a useful point which I have made a mental note of. Eventually I realised that, in this case, I needed to put the code into the 'ThisDocument_New 'procedure, instead of 'ThisDocument_Open'.
See also the 'Assembly Cannot Be Found' section of this troubleshooting article: Troubleshooting in Office at Run Time
My challenge now is: How do I pass parameters such as a client ID so that my code knows what data to fill in?
[UPDATE:
I got some replies to this last question: http://www.dotnet247.com/247reference/msgs/50/250487.aspx
My feeling is that, since all our users will be using IE, the best way might be to go for a really simple solution and use javascript to pass some structured data (XML?) into the clipboard (using .execCommand("Copy")), as in: http://www.dynamicdrive.com/dynamicindex11/copytext.htm
Presumably VSTO can then attempt to access the clipboard data on opening...]
[UPDATE 2:
This post has been listed on MSDN!