13

I have a bit of code that will open a Word 2007 (docx) document and update the appropriate CustomXmlPart (thus updating the Content Controls in the document itself as they are mapped to the CustomXmlPart) but can't work out how to save this as a new file.! Surely it can't be that hard!

My current thinking is that I need to open the template and copy the content into a new, blank document - file by file, updating the CustomXmlPart when I encounter it. Call me old fashioned but that sounds a little bit clunky to me!

Why can't I just do a WordprocessingDocument.SaveAs(filename); ...?

Please tell me I am missing something simple here.

Thanks in advance

DilbertDave
  • 3,406
  • 3
  • 33
  • 42
  • I thought that OpenXml was supposed to make things eaiser - pfft.! Leaving the above aside for the timebeing I had a look at the next task on the list - embedding a handful of docx files into a single docx (don't ask!) and I'm just giving myself a headache here! – DilbertDave Aug 05 '09 at 15:45
  • *easier* .. than hand-crafting the xml based on the spec ;) – JoeBrockhaus Oct 07 '14 at 22:06

5 Answers5

16

Are you referring to the OpenXml SDK? Unfortunately, as of OpenXml SDK 2.0, there's no SaveAs method. You'll need to:

  1. Make a temporary copy of your template file, naming it whatever you want.
  2. Perform your OpenXml changes on the above file.
  3. Save the appropriate sections (ie. using the .myWordDocument.MainDocumentPart.Document.Save() method for the main content or someHeaderPart.Header.Save() method for a particular header).
Ahmad Mageed
  • 94,561
  • 19
  • 163
  • 174
  • 7
    That's pretty much what I ended up doing - seems a bit of an omission to me. If you open a document and modify it then it stands to reason that you might want to save the updated version with a different name. – DilbertDave Aug 21 '09 at 10:52
  • 1
    The same can be accomplished if you read the file into MemoryStreams correct? I mean to avoid making copies of the file. – Pablo Romeo May 09 '13 at 17:24
  • @PabloRomeo I think that might be possible, but it's not an approach I tried back when I was working with OpenXml. You can probably work with the `MemoryStream` then save it to a desired file name in the end, if that's the goal. These links might help: [Working with In-Memory Open XML Documents](http://msdn.microsoft.com/en-us/library/office/ee945362%28v=office.11%29.aspx) and [Trouble with OpenXML and MemoryStreams?](http://amykinsgardiner.blogspot.com/2011/02/trouble-with-openxml-and-memorystreams.html) – Ahmad Mageed May 09 '13 at 18:35
2

OpenXml 2.8.1 has a SaveAs method that seems to do the trick.

var document = WordprocessingDocument.Open(specificationPath, true);
document.SaveAs("filePath/documentCopy.docx");
bwall
  • 984
  • 8
  • 22
1

Indeed you can, at least, in OpenXml SDK 2.5. However, watchout to work with a copy of the original file, because changes in the XML will be actually reflected in the file. Here you have the methods Load and Save of my custom class (after removing some validation code,...):

    public void Load(string pathToDocx)
    {
        _tempFilePath = CloneFileInTemp(pathToDocx);
        _document = WordprocessingDocument.Open(_tempFilePath, true);
        _documentElement = _document.MainDocumentPart.Document;
    }    

    public void Save(string pathToDocx)
    {
        using(FileStream fileStream = new FileStream(pathToDocx, FileMode.Create))
        {
            _document.MainDocumentPart.Document.Save(fileStream);
        }
    }

Having "_document" as a WordprocessingDocument instance.

1

You can use a MemoryStream to write the changes, rather than in the original file. Consequently, you can save that MemoryStream to a new file:

byte[] byteArray = File.ReadAllBytes("c:\\temp\\mytemplate.docx");
using (var stream = new MemoryStream())
{
    stream.Write(byteArray, 0, byteArray.Length);
    using (var wordDoc = WordprocessingDocument.Open(stream, true))
    {
       // Do work here
       // ...
       wordDoc.MainDocumentPart.Document.Save(); // won't update the original file 
    }
    // Save the file with the new name
    stream.Position = 0;
    File.WriteAllBytes("C:\\temp\\newFile.docx", stream.ToArray()); 
}
Boris Lipschitz
  • 9,236
  • 5
  • 53
  • 63
0

In Open XML SDK 2.5 Close saves changes when AutoSave is true. See my answer here: https://stackoverflow.com/a/36335092/3285954

Community
  • 1
  • 1
user3285954
  • 4,499
  • 2
  • 27
  • 19