By using of office
documents, it is often required to prepare some data for document before the
user opens it.
This scenario is typical
for web application. User goes online and downloads the document. However,
immediately before downloading the server should append some data to document,
so the user can change it.
After the user has changed
the data the document is uploaded on the server.
This is very common
scenario. To solve this problem it was required to install the office
application on the server. The web application then would start the application
by COM automation etc.
Such architecture was
never a way I recommended. Unfortunately, this was often the only way.
The VSTO offers a new
feature called “Data
Islands”. It is really
not a revolutionary feature, but it could have a huge impact on the
architecture of “Information Worker” applications.
VSTO data islands provide
two key features:
-
Persisting
(embedding) of the data in the document.
-
Manipulating
of embedded (persisted) data without of creating of the instance of the certain
office application.
Following example show how
to use data islands. The example consists of two small projects. The first one
is the VSTO (office) project based on WinWord and second one is the console
application simulating some external process, which manipulates the data
embedded in the document.
First, the data has to be
defined, which will be cached (embedded-persisted) in document. For this
purpose only serializable data can be used.
Then define corresponding
fields (not properties) as public and declare the attribute [Cached()].
In this example the string
‘Name’ and dataset ‘Ds’ are used.
When the document is
started first time both fields have to be set on some value. This ensures that
serialized values are stored in the cache.
using System;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using
Microsoft.VisualStudio.Tools.Applications.Runtime;
using Word =
Microsoft.Office.Interop.Word;
using Office =
Microsoft.Office.Core;
namespace WordDocument5
{
public partial
class ThisDocument
{
[Cached()]
public string Name;
[Cached()]
public DataSet Ds;
private
void ThisDocument_Startup(object sender, System.EventArgs
e)
{
if
(Ds == null)
Ds = new
DataSet();
if
(String.IsNullOrEmpty(Name))
Name = "-";
}
.
. .
}
}
Now let’s take a look on
the second projects. The example bellow shows how some application (independent
on office) can manipulate cached data. It shows how to write the data in the
cache and how to read it.
The method Write()
reads the content of the XML file, which is serialized RFID tag, and persists
it in the VSTO cache.
Please note that all
cached variables are stored in the collection HostItems. In this example
hard-coded value WordDocument5.ThisDocument is
used to retrieve the host (property containing cached values).
In general cached values
can be retrieved by using of following generic syntax:
doc.CachedData.HostItems(<ViewName>).CachedData(<DataName>)
where:
<ViewName>
The name of the „View“, which contains the data. If Winword is used the view
name is consisted as “DocumentName.ThisDocument”. Document name is the name of
the winword document and ThisDocument is the name of the class implementing
VSTO functionality. If Excel is used then each sheet represents one view.
<DataName> The name
of the cached variable, which is preserved by attribute Cached(). See
first example.
using System;
using System.Data;
using Microsoft.VisualStudio.Tools.Applications.Runtime;
namespace ConsoleApplication1
{
class Program
{
private
static string
m_Xml = @"abc.tag.xml";
// TODO:
Change this path.
private
static string
filename = @"D:\MyProjects\DaenetProjects\DiverseTests\VSTO\WordDocument5\WordDocument5\bin\Debug\WordDocument5.doc";
static void Main(string[] args)
{
if
(ServerDocument.IsCustomized(filename))
{
Write();
Read();
}
}
/// <summary>
/// Writes the data to document cache.
/// </summary>
static void Write()
{
if
(ServerDocument.IsCacheEnabled(filename))
{
using
(ServerDocument doc = new
ServerDocument(filename))
{
CachedDataHostItem
host = doc.CachedData.HostItems["WordDocument5.ThisDocument"];
host =
doc.CachedData.HostItems["WordDocument5.ThisDocument"];
CachedDataItem
dsItem = host.CachedData["Ds"];
System.Data.DataSet Ds = new DataSet();
Ds.ReadXml(m_Xml);
dsItem.SerializeDataInstance(Ds);
CachedDataItem
nameItem = host.CachedData["Name"];
nameItem.SerializeDataInstance("Damir2");
doc.Save();
}
}
}
/// <summary>
/// Reads the data from document cache.
/// </summary>
static void Read()
{
if
(ServerDocument.IsCacheEnabled(filename))
{
using
(ServerDocument doc = new
ServerDocument(filename))
{
CachedDataHostItem
host = doc.CachedData.HostItems["WordDocument5.ThisDocument"];
host =
doc.CachedData.HostItems["WordDocument5.ThisDocument"];
CachedDataItem
dsItem = host.CachedData["Ds"];
System.IO.StringReader xmlReader = new
System.IO.StringReader(dsItem.Xml);
System.IO.StringReader schemaReader = new
System.IO.StringReader(dsItem.Schema);
System.Data.DataSet Ds = new DataSet();
Ds.ReadXmlSchema(schemaReader);
Ds.ReadXml(xmlReader);
}
}
}
}
}
Some more information about this feature you can find here and here.
Damir Dobric
Posted
Apr 13 2006, 05:53 PM
by
Damir Dobric