VSTO 2.0 and Cached Data: Goodbye Hidden Sheets, Hello Server!
Paul Cornell blogs about cached data in VSTO 2.0.
I gotta tell you—cached data is one of features I’m most excited about in VSTO 2.0. First some background:
Office programming is different from traditional WinForms programming in that you are writing code that is associated with a document—a document that can move from person to person, from client to server, from server to client, etc. People don’t typically e-mail around WinForms programs, but they e-mail Office documents constantly. When they e-mail an Office document, they don’t expect to have to mail anything but the document—they don’t want to mail the document and say a related config or data file at the same time.
Also, it is assumed that an Office document can be used when you are offline—we often talk about the “on the plane” scenario. People expect Office solutions to work offline—they don’t always expect WinFoms or Web applications to work offline.
Finally, a lot of developers want to manipulate the contents of an Office document on the server without starting up Word or Excel. The new Office XML formats give you one way to do this (which is very cool and sexy), but generating Word XML or Excel XML on the server is complex. We wanted to provide developers with another way to populate an Office document on the server that doesn’t require them to learn the Word or Excel XML formats.
The cached data feature in VSTO 2.0 was designed around these aforementioned ideas: you always have a document associated with your application, documents move around, it is expected that a document will work offline, and that developers want an easier server story for Office to generate documents on the server.
So what is cached data? Quite simply, cached data lets you embed arbitrary data in a data island that VSTO 2.0 creates and manages for you inside the Office document. We see Excel developers do something similar to this all the time—they often use a “hidden sheet” to store additional data needed by their application.
We are now giving you the equivalent of this “hidden sheet” to store any data you want to associate with your Office document. Some of the data you store in the document will be data bound into the Office document and displayed all the time. Other data you store in the document might not be displayed all the time in the document or might be used for other purposes. For example, you can imagine that you might have a customers data set cached in a document, but you only data bind the customer’s name, address, and phone into the spreadsheet or document. Still, you keep the entire data set cached because you need to have the customer ID or other information.
It is super easy to start using cached data in VSTO 2.0. Here is the simplest code example in VB.NET:
Public Class ThisDocument
<Cached()> Public myCachedData As DataSet
Private Sub ThisDocument_Initialize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Initialize
If myCachedData Is Nothing Then
myCachedData = New DataSet()
myCachedData.ReadXml("\\data\customers.xml")
End If
End Sub
End Class
This is some simple code behind a Word document. In my code, you will notice that I declared a dataset (myCachedData). Three critical things to note:
1) myCachedData is declared as a field. Only fields can be used with the VSTO 2.0 cached data feature—a temporary variable cannot be cached.
2) I declared myCachedData but did not create an instance (that is, I didn’t write the code <Cached()> Public myCachedData as DataSet = New DataSet()). This is also important as we will see later.
3) Finally, I added an attribute to my declaration, the “Cached()” attribute. This is a way to mark this field so the VSTO 2.0 runtime knows to cache it in the document's data island.
Now, on to my code to handle the Initialize event (which fires each time the document is opened).
The first thing I do in my event handler is check if myCachedData Is Nothing. Why would I do this? Well, the first time this document runs, myCachedData will be nothing as I would expect. So I create a new instance of the data set and fill it in this example with an xml file containing customer information.
But what will then happen is when the user closes this document, Word will detect that the cached data has been changed and it will prompt the user to save the document. The user will save the document and along with the obvious contents of the document, the state of my data set (and any other fields I have marked as cached) will be saved into the document too.
On the second time the document is run (imagine it is now run on an airplane), the VSTO runtime will start up the customization again, but this time it notices that it has cached “myCachedData” in the document data island. So before any of my code gets run, the VSTO runtime will instantiate myCachedData from the data island. Now, when my Initialize code gets run the second time and I check if myCachedData Is Nothing, this will evaluate to false because the runtime has already created myCachedData for me—it will already be filled with the customers.xml that I loaded the first time I ran the document.
So you can imagine how you can use this feature to support offline. You can refresh the state of myCachedData if you have a connection available. If you don’t, you can just use the last cached version of myCachedData.
Finally, you can imagine how this now enables simple server scenarios. Imagine I’ve taken the myCachedData dataset and databound it to some of the contents of the document. Now what I want to do is fill the myCachedData dataset on the server when I serve this document up to a client on a web request. That way, the document is prepopulated with the data it needs before the user ever gets it. Also, this allows me to access the data bases on the server and not have to set up a way for the client to be able to hit my data sources. When the user opens the document on the client, the cached data will be loaded, data binding pulls the cached data into the document contents, and whammo--cached data populated on the server appears in my document.
On the server, we provide an object model that lets you read or write cached data from the data island without starting up Word or Excel. The code below opens mydoc.doc (without starting Word on the server). It then sets the cached data set “myCachedData” which is a member of the ThisDocument view class to a new value by setting new xml for the data set. The document is then saved and closed. You could run this code on the server to fill a document with data before sending it to the client.
Dim myServerDocument As New ServerDocument("c:\mydoc.doc")
myServerDocument.CachedDataManifest.Views("ThisDocument")._
CachedData("myCachedData").Xml = "<Customers>...</Customers>"
myServerDocument.Save()
myServerDocument.Close()
Finally, you might ask, what can I cache? Just data sets?
Well we certainly support data sets and typed data sets. But you can also cache any type that is XML Serializable. This means you can create your own custom types—look up tables, property bags, k-d-B-trees, whatever you want, and cache them in your document. Also, you can populate the contents of these custom types on the server using the ServerDocument class as shown above. Pretty cool huh!
Comments
- Anonymous
April 23, 2004
A sub storage in the compound documents, is there anything I am missing behind the exciting "cache" ? - Anonymous
April 25, 2004
Yes--effectively, this is what is happening behind the scenes. It is a substorage in the compound document that we serialize and deserialize field instances you've marked in your code. - Anonymous
April 29, 2004
So I am also excited about this. Calling a sub storage is a cheap way of minimizing the value. I think the true value comes in 2 ways:
1. Standardizing a storage mechanism for Office
2. Binding, binding, binding. If the cache data is bindable (I've personally made the mental leap that it is).. that is powerful. As a programmer i write code that manages populating the cache. Then I bind my data to the document and don't have to write UI code.
Is that possible? - Anonymous
April 30, 2004
Yes--this whole feature was really built around the data binding support in VSTO2. So you could populate the cache on the server in a document where you've already bound the cached data to UI elements. When the user opens the document the data binding moves the cached data (that you just changed or populated on the server) into the document automatically. - Anonymous
May 24, 2004
I can't actually get this feature to work. In VS 2005, build 40315 I add a class field with the Cached attribute, and in Document_Initialize I do the if( field == null ) check and it is always null. Even though I initialize the member when it is null and save the document on exit the data does not appear to persist. Does this have to do with the Start/StopCaching() methods which I also can't quite figure out? From this entry and a few presentations I've seen I thought it was mostly automatic when the attribute was used. Great feature -- I just can't get it working!
Thanks for your help! - Anonymous
May 24, 2004
Are you using Word or Excel? What is the type of your class field? - Anonymous
May 24, 2004
This is in Word. I added a class field now so I have a simple String and a DataSet. I need to correct my original post slightly. I wrote code to examine the document using the CustomizedDocument class and the CachedDataItem collection does show the names of my cached items, but they both have NULL for contents. - Anonymous
May 24, 2004
We had a bug in Word with regards to cached data that totally broke the cached data feature for Word. It will be fixed in the Beta 1 release. Excel should work--at least the DataSet based field. We are adding better support for anything that is XMLSerializable in Beta 2. - Anonymous
May 24, 2004
Thanks! That will save some of my hair from being pulled out! Can you also say a sentence or two about when Start/StopCaching() are used? The VS MSDN documentation has no info other than auto-gen class info.
Thanks! I really appreciate your help! - Anonymous
January 21, 2009
PingBack from http://www.keyongtech.com/1502255-hidden-text-in-word