Now that the new Open Packaging Conventions are here for us developers, a load of cool scenario’s become available. This example will show how to open a Word document using the WinFX packaging API, customize the document for a collection of customers , and save the document out again onto the filesystem, ready for mailing it.
When thinking about this scenario, you quickly find two ways of achieving this. The first is creating copies of the master document using File.Copy, and then open each copy individually using Package.Open(filePath). This of course generates loads of disk-io, not that nice so to say. Another option is to load the master document into memory, copy the document in memory, and next load the document from the copied memorybuffer using Package.Open(stream). Let’s do the second one, the first on is easy enough.
So the breakdown:
1. Open the package
2. Read all bytes into a memory buffer
3. Copy the memorybuffer, which copies the document
4. Modify the copied memorybuffer using the Packaging API
5. Save the copied document back onto the filesystem.
This is not actually that difficult to do, just run each step sequentially.
static void Main(string[] args)
{
DateTime start = DateTime.Now;
// Open the document
using (FileStream fs = new FileStream(
"Demo.docx", FileMode.Open, FileAccess.ReadWrite))
{
// Load it into a memorybuffer
using (MemoryStream ms = new MemoryStream())
{
byte[] buffer = new byte[1024];
int bytesRead = fs.Read(buffer, 0, 1024);
while (bytesRead > 0)
{
ms.Write(buffer, 0, bytesRead);
bytesRead = fs.Read(buffer, 0, 1024);
}
// Create a few copies of the document
for (int i = 0; i < 100; i++)
{
// Copy the memorybufer, which copies the document
MemoryStream docStream = new MemoryStream();
ms.WriteTo(docStream);
// Open a Package from the copied stream
// Need to open with FileAccess.ReadWrite or get exceptions
Package package = Package.Open(
docStream, FileMode.OpenOrCreate, FileAccess.ReadWrite);
// Simulate some modifications, which of course can be embedding XML
package.PackageProperties.Title = "Test " + i;
package.Close();
// Write the Package back to disk
using (FileStream writer = new FileStream(
"Demo" + i + ".docx", FileMode.Create, FileAccess.ReadWrite))
{
docStream.WriteTo(writer);
}
}
}
}
Console.WriteLine("It took: " + (DateTime.Now - start));
}