swaroop
swaroop

Reputation: 11

OpenXMLSDk: Insert Images Corrupted the document

I need to insert images in different pages. All the images will be different and it will be inserted in to different location like table cells.

I have tried the example in the MSDN link -http://msdn.microsoft.com/en-us/library/office/bb497430.aspx

But after inserting the document is getting corrupted. Insertion of one image with the same code works , but i try inserting another image document is getting corrupted. RelationshipID is passed different from addImagePart creates new relationshipID.

I tried opening recovered docuemnt and the corrupted document in Open XMl SDk 2.5 Productivity Tool and i Could see the images are stored in /media/ folder in the corrupted document and /word/media/ in the recovered document. Is this would be the reason for getting corrupted? http://tinypic.com/r/r1fozp/5 Pleas help me with this as i'm stuck with this for some time

I'm using OS: Windows 8, OpenXMLSDK 2.5 and office 2013

regards,

Swaroop

Upvotes: 0

Views: 1315

Answers (2)

Chris Roberts
Chris Roberts

Reputation: 486

OK, so this is a very old question, but I've been tearing my hair out with it today so wanted to post an answer for anyone searching in future.

If you're trying to insert multiple images, the corrupt document error is caused by duplicate IDs within the document. Notice the lines:

new DW.DocProperties()
{
    Id = (UInt32Value)1U,
    Name = "Picture 1"
}

and:

new PIC.NonVisualDrawingProperties()
{
    Id = (UInt32Value)0U,
    Name = "New Bitmap Image.jpg"
}

If you've used the code "as is" from the MSDN example then multiple elements will be added to the document with the same ID, causing XML validation errors that corrupt the document. The solution for me was to increment the ID each time.

I created a little image helper class, based on the abstracted example here, that takes an image start ID when constructing and then increments the value each time it is called, as follows:

using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Wordprocessing;
using A = DocumentFormat.OpenXml.Drawing;
using DW = DocumentFormat.OpenXml.Drawing.Wordprocessing;

namespace DOCXExporter
{
    class ImageHelper
    {
        private UInt32Value _docPropImageId;

        public ImageHelper(UInt32Value startImageId)
        {
            _docPropImageId = startImageId;
        }

        public Drawing GetImageElement(
            string imagePartId,
            string fileName,
            string pictureName,
            double width,
            double height)
        {
            // Increment ID values
            _docPropImageId += 1;

            double englishMetricUnitsPerInch = 914400;
            double pixelsPerInch = 96;

            //calculate size in emu
            double emuWidth = width * englishMetricUnitsPerInch / pixelsPerInch;
            double emuHeight = height * englishMetricUnitsPerInch / pixelsPerInch;

            var element = new Drawing(
                new DW.Inline(
                    new DW.Extent { Cx = (Int64Value)emuWidth, Cy = (Int64Value)emuHeight },
                    new DW.EffectExtent { LeftEdge = 0L, TopEdge = 0L, RightEdge = 0L, BottomEdge = 0L },
                    new DW.DocProperties { Id = _docPropImageId, Name = pictureName },
                    new DW.NonVisualGraphicFrameDrawingProperties(
                    new A.GraphicFrameLocks { NoChangeAspect = true }),
                    new A.Graphic(
                        new A.GraphicData(
                            new A.Pictures.Picture(
                                new A.Pictures.NonVisualPictureProperties(
                                    new A.Pictures.NonVisualDrawingProperties { Id = (_docPropImageId + 1), Name = fileName },
                                    new A.Pictures.NonVisualPictureDrawingProperties()),
                                new A.Pictures.BlipFill(
                                    new A.Blip(
                                        new A.BlipExtensionList(
                                            new A.BlipExtension { Uri = "{28A0092B-C50C-407E-A947-70E740481C1C}" }))
                                    {
                                        Embed = imagePartId,
                                        CompressionState = A.BlipCompressionValues.Print
                                    },
                                            new A.Stretch(new A.FillRectangle())),
                                new A.Pictures.ShapeProperties(
                                    new A.Transform2D(
                                        new A.Offset { X = 0L, Y = 0L },
                                        new A.Extents { Cx = (Int64Value)emuWidth, Cy = (Int64Value)emuHeight }),
                                    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"
                });

            return element;
        }
    }
}

Instantiate the class with a seed ID before you add any images to your document:

var imageHelper = new ImageHelper(1U);

And then use when adding images to your table:

var mainPart = wordDocument.MainDocumentPart;  
var imagePart = mainPart.AddImagePart(ImagePartType.Jpeg);
using (var mediaStream = new FileStream(imageFilename, FileMode.Open))
{
    imagePart.FeedData(mediaStream);
}

var imageElement = imageHelper.GetImageElement(
    mainPart.GetIdOfPart(imagePart),
    imageFilename,
    Guid.NewGuid().ToString(),
    260, 208);

var imgPara = new Paragraph(new Run(imageElement));
cell.Append(imgPara);

Hope this helps!

Upvotes: 3

Hoodah
Hoodah

Reputation: 29

Make sure to call WordprocessingDocument.Close(), the relationships are not added otherwise. In the MSDN sample they neglect to point this out.

Upvotes: 2

Related Questions