Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Embedded documents with images breaks "Save As" on Word for Mac #645

Closed
paulresdat opened this issue Dec 14, 2019 · 3 comments
Closed

Embedded documents with images breaks "Save As" on Word for Mac #645

paulresdat opened this issue Dec 14, 2019 · 3 comments

Comments

@paulresdat
Copy link

@paulresdat paulresdat commented Dec 14, 2019

Is this a:

  • Issue with the OpenXml library
  • Question on library usage

Description

Using OpenXML, appending a word document with embedded images into another word document using AddAlternativeFormatImportPart(AlternativeFormatImportPartType.WordprocessingML, altChunkId) causes an issue where the user can not "Save" or "Save As" when altering the content in Word for Mac.

Information

  • .NET Target: .NET Framework, .NET Core 3
  • DocumentFormat.OpenXml Version: 2.9.1

Repro

  1. Create a new Console App in Visual Studio on Mac
  2. Add a folder to the top level called "Docs"
  3. Download the Nuget dependency DocumentFormat.OpenXml
  4. Create a new word doc named "test-source.docx"
    1. Put some test text in there, doesn't matter what
    2. Add the document to the solution in "Docs" folder
    3. Change the property to "Copy always"
  5. Create a new word doc named "test-append.docx" (the embedded word doc)
    1. Put in some test text at the top
    2. Copy over a jpg of your choice. The image type I used to reproduce is a jpg. I fetched mine from http://apod.nasa.gov/apod/ , one of their big pics should do it.
    3. Add to the "Docs" folder in the solution
    4. Change property of document to "Copy always"
  6. Copy paste the code below into your Program.cs file:
using System.IO;
using System.Linq;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using Text = DocumentFormat.OpenXml.Wordprocessing.Text;

namespace TestWordAppend
{
    class Program
    {
        static void Main(string[] args)
        {
            var destinationDoc = "Docs/test-destination.docx";
            var sourceDoc = "Docs/test-source.docx";
            var appendedDoc = "Docs/test-append2.docx";

            File.Delete(destinationDoc);
            File.Copy(sourceDoc, destinationDoc);

            using (var doc = WordprocessingDocument.Open(destinationDoc, true))
            {
                var body = doc.MainDocumentPart.Document.Body;

                var p2 = body.InsertAfter(
                    new Paragraph(
                        new ParagraphProperties(
                            new PageBreakBefore()
                    )),
                    body.Elements<Paragraph>().Last()
                );


                var altChunkId = "AltChunkId";
                var chunk = doc.MainDocumentPart.AddAlternativeFormatImportPart(
                    AlternativeFormatImportPartType.WordprocessingML,
                    altChunkId);

                using (var fs = File.Open(appendedDoc, FileMode.Open))
                    chunk.FeedData(fs);

                var altChunk = new AltChunk { Id = altChunkId };
                var run = new Run(new TabChar(), new Text(appendedDoc), new Break());
                run.PrependChild(new RunProperties { RunStyle = new RunStyle { Val = "Bold" } });
                var fileP = p2.InsertAfterSelf(new Paragraph());
                fileP.Append(run);
                run = new Run(new TabChar(), new Text("Uploaded by: "), new TabChar(), new Text("Test User"));
                run.PrependChild(new RunProperties { RunStyle = new RunStyle { Val = "Italic" } });
                fileP.Append(run);

                body.Append(altChunk);
                doc.MainDocumentPart.Document.Save();
            }
        }
    }
}

Observed

When I open the destination document using Word on Mac, I will indeed see the document contents embedded in the destination document, however I can no longer utilize "Save" or "Save As". Upon clicking "save" on a "Save As" when changing the name of the file, you will see the file name revert back to the original document name in the title and when you go to your "Save As" destination, you will not find a new document. This problem does not exist in Word for Windows.

Expected

The document should be able to be altered and saved within the MacOS Word application.

@ThomasBarnekow

This comment has been minimized.

Copy link
Contributor

@ThomasBarnekow ThomasBarnekow commented Dec 14, 2019

@paulresdat, thank you very much for this excellent issue description, which is a perfect example of how one should do it.

Based on your description, I reproduced the behavior. Microsoft Word for Mac shows the behavior you describe, and Microsoft Word for Windows works as expected. I even made some changes to your sample code to see whether that makes a difference because your sample code has a few issues:

  • At least the standard Word template does not have any character styles called "Bold" or "Italic," and I am not sure whether they exist in your sample documents. Therefore, I replaced the RunStyle instances with Bold and Italic instances, which apply direct formatting to those runs.
  • Your runs contain more children (e.g., two Text instances) than Microsoft Word would produce in its Open XML markup. While the standard allows that, I wanted to rule that out as a potential issue.
  • While a w:altChunk element is a child of w:body, it should not come as the last element, which should be a w:sectPr if it exists. Thus, I fixed that as well in my code.

Finally, I streamlined the code a little and cast it as a unit test. Here's the result:

using System;
using System.IO;
using System.Linq;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using Xunit;

namespace CodeSnippets.Tests.OpenXml.Wordprocessing
{
    public class AltChunkImagesTests
    {
        private static AltChunk CreateAltChunkFromWordDocument(
            string sourcePath,
            WordprocessingDocument destWordDocument)
        {
            string altChunkId = "AltChunkId-" + Guid.NewGuid();

            AlternativeFormatImportPart chunk = destWordDocument.MainDocumentPart.AddAlternativeFormatImportPart(
                AlternativeFormatImportPartType.WordprocessingML, altChunkId);

            using FileStream fs = File.Open(sourcePath, FileMode.Open);
            chunk.FeedData(fs);

            return new AltChunk { Id = altChunkId };
        }

        [Fact]
        public void CanAppendDocumentWithImage()
        {
            const string destinationDoc = "test-destination.docx";
            const string sourceDoc = "Resources/test-source.docx";
            const string appendedDoc = "Resources/test-append.docx";

            File.Copy(sourceDoc, destinationDoc, true);

            using WordprocessingDocument destWordDocument = WordprocessingDocument.Open(destinationDoc, true);
            Body body = destWordDocument.MainDocumentPart.Document.Body;

            Paragraph p2 = body.InsertAfter(
                new Paragraph(
                    new ParagraphProperties(
                        new PageBreakBefore()),
                    new Run(
                        new RunProperties(new Bold()),
                        new TabChar(),
                        new Text(appendedDoc)),
                    new Run(
                        new Break()),
                    new Run(
                        new RunProperties(new Italic()),
                        new TabChar(),
                        new Text("Uploaded by:")),
                    new Run(
                        new RunProperties(new Italic()),
                        new TabChar(),
                        new Text("Test User"))),
                body.Elements<Paragraph>().Last());

            p2.InsertAfterSelf(
                CreateAltChunkFromWordDocument(appendedDoc, destWordDocument));
        }
    }
}

Unfortunately, as already mentioned above, Microsoft Word for Mac shows the same behavior even with my "improved" version, which works perfectly well with Microsoft Word for Windows. I've also uploaded test-destination.docx to SharePoint and opened the document in Word Online, which also shows the appended document (test-append.docx) with the image. Word Online is just not able to edit the document, saying that it contains objects that the online version does not support. Instead, it asks you to open the document with the Word application.

So, what do we have now?

  • The document is displayed correctly by Microsoft Word for Windows and Mac and by Word Online.
  • The document can be edited and saved by Microsoft Word for Windows.
  • The document can't be edited by Microsoft Word Online, because it contains features that are not supported by Microsoft Word Online (which is to be expected as it does not support all functions).
  • The document can be edited with Microsoft Word for Mac, but it can't be saved.

Thus, my strong hypothesis is that it is a bug (or limitation in conjunction with a usability issue) of Microsoft Word for Mac rather than an issue with the Open XML SDK.

Would you be able to test this with another application that supports Open XML? Unfortunately, I don't have any other wordprocessing applications that I could use for testing.

@paulresdat

This comment has been minimized.

Copy link
Author

@paulresdat paulresdat commented Dec 17, 2019

@ThomasBarnekow - thank you for taking the timeout to test this and for the kind words! 👍

I'm in the process of downloading Open Office so I will follow up with a verdict on a different applicaiton. However as far as our environment at work, we do not use Open Office. We're tied to Microsoft and so a work around to use another application won't suffice as a solution for us.

However I've come up with a code work around that basically copies the internals of one document to another. To me this is hackish but could suffice for the interim. I have a question in the meantime: If this is a bug with Microsoft Word, how can this issue be escalated to the Word team so that it can be addressed for Word on Mac?

@twsouthwick

This comment has been minimized.

Copy link
Collaborator

@twsouthwick twsouthwick commented Mar 24, 2020

Thanks @ThomasBarnekow for your investigation. As this is not an issue with the SDK, i'll close the issue. Please use stack overflow for any Q&A of how to use the SDK. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants
You can’t perform that action at this time.