1
votes

I am attempting to use OpenXML with C# to create a DOCX word document. The text and formatting on the document work very well. But, when I add an image to the document, Word 2007 will not open the document. It's detailed error is "Unspecified Error".

Below is a program that demonstrates the error. The resultant .DOCX opens fine in Word 2010 but fails in Word 2007. I have tried the 2.0 and 2.5 versions of the SDK. Any thoughts would be appreciated.

using System.IO;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using A = DocumentFormat.OpenXml.Drawing;
using PIC = DocumentFormat.OpenXml.Drawing.Pictures;
using DW = DocumentFormat.OpenXml.Drawing.Wordprocessing;

namespace ImageTest2007a
{
    class Program
    {
        static void Main(string[] args)
        {
            string imagefilename = @"c:\work\temp\ANI.jpg";

            // Create the Word document
            using (WordprocessingDocument wordDocument = WordprocessingDocument.Create(@"C:\temp\t1.docx", WordprocessingDocumentType.Document))
            {
                // Create the "Main Part" of the document.  Not really used much externally here.
                MainDocumentPart theDoc = wordDocument.AddMainDocumentPart(); // Not directly referenced as 'theDOC'.  The reference wordDocument.MainDocumentPart is used.
                theDoc.Document = new Document();

                // Create and attach the body to the document.  The body of the document is where the document content is placed.
                Body theBody = theDoc.Document.AppendChild(new Body());  // Not directly referenced as 'body'.  The reference within wordDocument.MainDocumentPart.Document.Body is used.

                // attach the image

                ImagePart imagePart = theDoc.AddImagePart(ImagePartType.Png);

                using (FileStream stream = new FileStream(imagefilename, FileMode.Open))
                {
                    imagePart.FeedData(stream);
                }

                AddImageToBody(wordDocument, theDoc.GetIdOfPart(imagePart));
                theDoc.Document.Save();
            }
        }

        private static void AddImageToBody(WordprocessingDocument wordDoc, string relationshipId)
        {
            // Define the reference of the image.
            var element =
                 new Drawing(
                     new DW.Inline(
                         new DW.Extent() { Cx = 990000L, Cy = 792000L },
                         new DW.EffectExtent()
                         {
                             LeftEdge = 0L,
                             TopEdge = 0L,
                             RightEdge = 0L,
                             BottomEdge = 0L
                         },
                         new DW.DocProperties()
                         {
                             Id = (UInt32Value)1U,
                             Name = "Picture 1"
                         },
                         new DW.NonVisualGraphicFrameDrawingProperties(
                             new A.GraphicFrameLocks() { NoChangeAspect = true }),
                         new A.Graphic(
                             new A.GraphicData(
                                 new PIC.Picture(
                                     new PIC.NonVisualPictureProperties(
                                         new PIC.NonVisualDrawingProperties()
                                         {
                                             Id = (UInt32Value)0U,
                                             Name = "New Bitmap Image.jpg"
                                         },
                                         new PIC.NonVisualPictureDrawingProperties()),
                                     new PIC.BlipFill(
                                         new A.Blip(
                                             new A.BlipExtensionList(
                                                 new A.BlipExtension()
                                                 {
                                                     Uri =
                                                        "{28A0092B-C50C-407E-A947-70E740481C1C}"
                                                 })
                                         )
                                         {
                                             Embed = relationshipId,
                                             CompressionState =
                                             A.BlipCompressionValues.Print
                                         },
                                         new A.Stretch(
                                             new A.FillRectangle())),
                                     new PIC.ShapeProperties(
                                         new A.Transform2D(
                                             new A.Offset() { X = 0L, Y = 0L },
                                             new A.Extents() { Cx = 990000L, Cy = 792000L }),
                                         new A.PresetGeometry(
                                             new A.AdjustValueList()
                                         )
                                         { Preset = A.ShapeTypeValues.Rectangle }))
                             )
                             { Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" })
                     )
                     {
                         DistanceFromTop = (UInt32Value)0U,
                         DistanceFromBottom = (UInt32Value)0U,
                         DistanceFromLeft = (UInt32Value)0U,
                         DistanceFromRight = (UInt32Value)0U,
                         EditId = "50D07946"
                     });

            // Append the reference to body, the element should be in a Run.
            wordDoc.MainDocumentPart.Document.Body.AppendChild(new Paragraph(new Run(element)));
        }



    }
}
1
.DOCX is actually just a zip file. Create a file in Word 2007 that mimics what you are trying to achieve. Save it, open as a zip and compare the contents to the one you created programatically. - MikeH
Specifically all the new office formats (with a X) are just XML Files, in a zip file that got renamed. It is indeed possibly to modify them using the ZipArchieve and XML Related classes. The definition is actually public. I would first exclude that there are any issues with that Word 2007 installation and it's Converter. Any chance you could set up a Word 2007 in a Virtual Machine? - Christopher
Adding to what @MikeH says: Install the Open XML SDK and use its Productivity Tool to compare a Word 2007 to a Word 2010 document. FWIW I vaguely recall that you need to set certain compatibility options for Word 2007 and you certainly can't include features not available in that version. - Cindy Meister

1 Answers

0
votes

I faced a similar problem with a previously created document (created in Word 2007 and later the picture inserted by code). I don't know if creating the document from code makes it compatible with Word 2007. If it does, then the problem can be in the image insertion.

The problem with the image insertion was the EditId property, which exists in the schema of Word 2010, but not in word 2007. If you comment this assignment in the code the document opens without a problem in Word 2007 (and the image displays fine):

                 {
                     DistanceFromTop = (UInt32Value)0U,
                     DistanceFromBottom = (UInt32Value)0U,
                     DistanceFromLeft = (UInt32Value)0U,
                     DistanceFromRight = (UInt32Value)0U,
                     //EditId = "50D07946"
                 });

Updated

I've tested doing it all for code (create the document and insert the image) and opens in Word 2007 without a problem, so definitely the problem of compatibility is EditId property.