Danicco
Danicco

Reputation: 1673

OpenXml: How to change a .docx file and use without saving it?

I have a .docx file that serve as a base for exporting a document with some client data.

I need to open the document, change it's content's according to the client, export it, and don't save it.

How can I do this?

// - Opening the document
WordprocessingDocument _document = null;
try
{
    // - Setting to false else it'll save the document as I change it
    _document = WordprocessingDocument.Open(filePath, false);
    _isOpen = true;
}
catch (Exception ex) { }

// - Doing some changes
foreach (Text element in _document.MainDocumentPart.Document.Body.Descendants<Text>())
{
    if (element.Text.Contains("#Client1#"))
    {
        element.Text = element.Text.Replace("#Client1#", "Bananas");
    }
}

using (StreamReader stream = new StreamReader(_document.MainDocumentPart.GetStream()))
{
    // - This stream is unchanged!
}

Upvotes: 0

Views: 1162

Answers (1)

Danicco
Danicco

Reputation: 1673

After some testing around, I managed to make it work with this:

public void Main(string[] args)
{
    // - Don't open the file directly, but from a stream and remember it.
    string fileName = "myDoc.docx";
    byte[] fileByteArray = File.ReadAllBytes(fileName);

    // - Don't forget to dispose this if you're using a manager-like class
    MemoryStream mStream = new MemoryStream(fileByteArray);

    // - Now this doesn't reflect the same document in your HD, but a copy in memory
    WordprocessingDocument document = WordprocessingDocument.Open(mStream, true);

    // - Changing the document
    ReplaceText("#Client1#", "Bananas");

    // - This won't overwrite your original file! 
    // - And this is required to "commit" the changes to the document
    document.MainDocumentPart.Document.Save();

    // - When you want to use the stream, you'll have to reset the position
    long current = mStream.Position;
    mStream.Position = 0;

    // - Use the stream (Response doesn't exist in this console program, but this is the idea)
    Response.AppendHeader("Content-Disposition", "attachment;filename=myDoc.docx");
    Response.ContentType = "application/vnd.ms-word.document";
    mStream.CopyTo(Response.OutputStream);
    Response.End();

    mStream.Position = current;

    // - If you want to overwrite the original too
    using (WordprocessingDocument document2 = WordprocessingDocument.Open(fileName, true, new OpenSettings() { AutoSave = false }))
    { 
        document2.MainDocumentPart.Document.Save(document.MainDocumentPart);            
    }
}

Upvotes: 1

Related Questions