Open XML SDK: opening a Word template and saving to a different file-name
Asked Answered
P

2

3

This one very simple thing I can't find the right technique. What I want is to open a .dotx template, make some changes and save as the same name but .docx extension. I can save a WordprocessingDocument but only to the place it's loaded from. I've tried manually constructing a new document using the WordprocessingDocument with changes made but nothing's worked so far, I tried MainDocumentPart.Document.WriteTo(XmlWriter.Create(targetPath)); and just got an empty file.

What's the right way here? Is a .dotx file special at all or just another document as far as the SDK is concerned - should i simply copy the template to the destination and then open that and make changes, and save? I did have some concerns if my app is called from two clients at once, if it can open the same .dotx file twice... in this case creating a copy would be sensible anyway... but for my own curiosity I still want to know how to do "Save As".

Pyrognostics answered 23/7, 2010 at 9:39 Comment(0)
W
6

I would suggest just using File.IO to copy the dotx file to a docx file and make your changes there, if that works for your situation. There's also a ChangeDocumentType function you'll have to call to prevent an error in the new docx file.

            File.Copy(@"\path\to\template.dotx", @"\path\to\template.docx");

            using(WordprocessingDocument newdoc = WordprocessingDocument.Open(@"\path\to\template.docx", true))
            {
                newdoc.ChangeDocumentType(WordprocessingDocumentType.Document);
                //manipulate document....
            }
Walther answered 28/7, 2010 at 19:52 Comment(0)
M
0

While M_R_H's answer is correct, there is a faster, less IO-intensive method:

  1. Read the template or document into a MemoryStream.
  2. Within a using statement:
    • open the template or document on the MemoryStream.
    • If you opened a template (.dotx) and you want to store it as a document (.docx), you must change the document type to WordprocessingDocumentType.Document. Otherwise, Word will complain when you try to open the document.
    • Manipulate your document.
  3. Write the contents of the MemoryStream to a file.

For the first step, we can use the following method, which reads a file into a MemoryStream:

public static MemoryStream ReadAllBytesToMemoryStream(string path)
{
    byte[] buffer = File.ReadAllBytes(path);
    var destStream = new MemoryStream(buffer.Length);
    destStream.Write(buffer, 0, buffer.Length);
    destStream.Seek(0, SeekOrigin.Begin);
    return destStream;
}

Then, we can use that in the following way (replicating as much of M_R_H's code as possible):

// Step #1 (note the using declaration)
using MemoryStream stream = ReadAllBytesToMemoryStream(@"\path\to\template.dotx");

// Step #2
using (WordprocessingDocument newdoc = WordprocessingDocument.Open(stream, true)
{
    // You must do the following to turn a template into a document.
    newdoc.ChangeDocumentType(WordprocessingDocumentType.Document);

    // Manipulate document (completely in memory now) ...
}

// Step #3
File.WriteAllBytes(@"\path\to\template.docx", stream.GetBuffer());

See this post for a comparison of methods for cloning (or duplicating) Word documents or templates.

Mokpo answered 28/11, 2019 at 17:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.