none
Problem with OpenXML 2.0 and PowerPoint 2007/2010 RRS feed

  • Question

  • I am using OpenXML 2.0 SDK to generate power point files from a list of Bitmaps that are passed in.  The idea is that I am already generating the slide in the form of an image, just need to create a presentation that puts one image per slide.   I created the following code from various different articles and SDK documentation.   When I call the method CreateSlides and pass in a list of bitmap images it generates the powerpoint with one image per slide just fine.  the template files (2007.pptx and 2010.pptx) are created by powerpoint of the same version with no slides like the sdk directs.  If I run the resulting presentation through validation it comes up with no errors at all.   The issues I am seeing are when you open the document with powerpoint 2007 and/or powerpoint 2010.  Here are the results:

    Open with PowerPoint 2010:  It errors saying PowerPoint found and error with the content and could repair it.  User hits repair and all the slides show up fine.

    Open with PowerPoint 2007:  It errors that PowerPoint found issues and user hits repair.  No slides show up at all.   

    I have been over and over this code and do not understand why powerpoint would be needing to repair this.   I expanded both the output pptx and the repaired version and did diffs on all the files.  All I am seeing is some renaming of rId's.  and Slide.xml is being renamed to Slide1.xml.  I have changed the way I was generating rId's several times to make sure it wasn't that, all of the rIds that I am putting in there should be unique.

    Can anyone point me in the right direction?  I am not understanding why this is having issues.

     
     	private MemoryStream CreateSlides(List<Bitmap> images, FileFormatVersions ver = FileFormatVersions.Office2010)
            {
                string relId;
                SlideId slideId;
                MemoryStream template = new MemoryStream();
     
                // Slide identifiers have a minimum value of greater than or equal to 256
                // and a maximum value of less than 2147483648. Assume that the template
                // presentation being used has no slides.
                uint currentSlideId = 256;
     
                //string imageFileNameNoPath;
     
                long imageWidthEMU = 0;
                long imageHeightEMU = 0;
     
                // Open the new presentation.
                Stream s = null;
                OpenSettings settings = new OpenSettings() { MarkupCompatibilityProcessSettings = new MarkupCompatibilityProcessSettings(MarkupCompatibilityProcessMode.ProcessAllParts, ver) };
     
                switch (ver)
                {
                    case FileFormatVersions.Office2007:
                        //s = Assembly.GetAssembly(this.GetType()).GetManifestResourceStream("WriteOn.DocumentGenerator.2007.pptx");
                        s = File.OpenRead(@"C:\2007.pptx");
                        break;
                    case FileFormatVersions.Office2010:
                        //s = Assembly.GetAssembly(this.GetType()).GetManifestResourceStream("WriteOn.DocumentGenerator.2010.pptx");
                        s = File.OpenRead(@"C:\2010.pptx");
                        break;
                }
                //Copy the stream into our memory stream
                CopyStream(s, template);
               
                
                using (PresentationDocument newDeck = PresentationDocument.Open(template, true, settings))
                {
                    PresentationPart presentationPart = newDeck.PresentationPart;
     
                    // Reuse the slide master part. This code assumes that the template presentation
                    // being used has at least one master slide.
                    var slideMasterPart = presentationPart.SlideMasterParts.First();
     
                    // Reuse the slide layout part. This code assumes that the template presentation
                    // being used has at least one slide layout.
                    var slideLayoutPart = slideMasterPart.SlideLayoutParts.First();
     
                    // If the new presentation doesn't have a SlideIdList element yet then add it.
                    if (presentationPart.Presentation.SlideIdList == null)
                        presentationPart.Presentation.SlideIdList = new SlideIdList();
     
                    int imageId = 1;
                    // Loop through each image file creating slides in the new presentation.
                    foreach (Bitmap curimage in images)
                    {
                        // Create a unique relationship id based on the current slide id.
                        relId = rid;
                        string embedName = rid;// "rId" + 1;
     
                        // Get the bytes, type and size of the image.
                        ImagePartType imagePartType = ImagePartType.Png;
                        byte[] imageBytes = GetImageData(curimage, ref imagePartType, ref imageWidthEMU, ref imageHeightEMU);
     
                        // Create a slide part for the new slide.
                        var slidePart = presentationPart.AddNewPart<SlidePart>(relId);
                        Slide sld = GenerateSlidePart("myImage" + imageId, "myImage" + imageId, imageWidthEMU, imageHeightEMU, embedName);
                        sld.Save(slidePart);
     
                        // Add the relationship between the slide and the slide layout.
                        slidePart.AddPart<SlideLayoutPart>(slideLayoutPart);
     
                        // Create an image part for the image used by the new slide.
                        // A hardcoded relationship id is used for the image part since
                        // there is only one image per slide. If more than one image
                        // was being added to the slide an approach similar to that 
                        // used above for the slide part relationship id could be
                        // followed, where the image part relationship id could be
                        // incremented for each image part.
                        var imagePart = slidePart.AddImagePart(imagePartType, embedName);
                        GenerateImagePart(imagePart, imageBytes);
                        slidePart.Slide.Save();
     
                        // Add the new slide to the slide list.
                        slideId = new SlideId();
                        slideId.RelationshipId = relId;
                        slideId.Id = currentSlideId;
                        presentationPart.Presentation.SlideIdList.Append(slideId);
     
                        // Increment the slide id;
                        currentSlideId++;
                        imageId++;
                    }
     
                    // Save the changes to the slide master part.
                    slideMasterPart.SlideMaster.Save();
     
                    //OpenXmlValidator validator = new OpenXmlValidator();
                    //var errors = validator.Validate(presentationPart);
                    // Save the changes to the new deck.
                    presentationPart.Presentation.Save();
                    
                }
     
                template.Flush();
                File.WriteAllBytes(@"J:\test.pptx", template.GetBuffer());
                return template;
            }
     
     
            public static void CopyStream(Stream input, Stream output)
            {
     
                byte[] buffer = new byte[16 * 1024];
                int read;
                while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
                {
                    output.Write(buffer, 0, read);
                }
            }
     
            private static int _rid = 10;
            private static string rid { get { return "rId" + _rid++; } }
     
            private static byte[] GetImageData(Bitmap imageFile, ref ImagePartType imagePartType, ref long imageWidthEMU, ref long imageHeightEMU)
            {
                byte[] imageFileBytes;
     
                // Get the dimensions of the image in English Metric Units (EMU)
                // for use when adding the markup for the image to the slide.
                imageWidthEMU =
                    (long)((imageFile.Width / imageFile.HorizontalResolution) * 914400L);
                imageHeightEMU =
                    (long)((imageFile.Height / imageFile.VerticalResolution) * 914400L);
     
                imagePartType = ImagePartType.Png;
                MemoryStream ms = new MemoryStream();
                imageFile.Save(ms, ImageFormat.Png);
                imageFileBytes = ms.ToArray();
                return imageFileBytes;
            }
     
            private static Slide GenerateSlidePart(string imageName, string imageDescription, long imageWidthEMU, long imageHeightEMU, string embedName)
            {
                var element =
                    new Slide(
                        new CommonSlideData(
                            new ShapeTree(
                                new NonVisualGroupShapeProperties(
                                    new NonVisualDrawingProperties() { Id = (UInt32Value)1U, Name = "" },
                                    new NonVisualGroupShapeDrawingProperties()),
                                new GroupShapeProperties(
                                    new a.TransformGroup(
                                        new a.Offset() { X = 0L, Y = 0L },
                                        new a.Extents() { Cx = 0L, Cy = 0L },
                                        new a.ChildOffset() { X = 0L, Y = 0L },
                                        new a.ChildExtents() { Cx = 0L, Cy = 0L })),
                                new DocumentFormat.OpenXml.Presentation.Picture(
                                    new NonVisualPictureProperties(
                                        new NonVisualDrawingProperties() { Id = (UInt32Value)4U, Name = imageName, Description = imageDescription },
                                        new NonVisualPictureDrawingProperties(
                                            new a.PictureLocks() { NoChangeAspect = true })),
                                    new BlipFill(
                                        new a.Blip() { Embed = embedName },
                                        new a.Stretch(
                                            new a.FillRectangle())),
                                    new ShapeProperties(
                                        new a.Transform2D(
                                            new a.Offset() { X = 0L, Y = 0L },
                                            new a.Extents() { Cx = imageWidthEMU, Cy = imageHeightEMU }),
                                        new a.PresetGeometry(
                                            new a.AdjustValueList()
                                        ) { Preset = a.ShapeTypeValues.Rectangle })))),
                        new ColorMapOverride(
                            new a.MasterColorMapping())
                            );
                
                return element;
            }
     
            private static void GenerateImagePart(OpenXmlPart part, byte[] imageFileBytes)
            {
                // Write the contents of the image to the ImagePart.
                using (BinaryWriter writer = new BinaryWriter(part.GetStream()))
                {
                    writer.Write(imageFileBytes);
                    writer.Flush();
                }
            }
     
            
     
     
            public static Bitmap BytesToBitmap(byte[] byteArray)
            {
                System.Drawing.ImageConverter ic = new System.Drawing.ImageConverter();
                Bitmap img = ic.ConvertFrom(byteArray) as Bitmap;
                return img;
            }

    Wednesday, July 11, 2012 1:27 AM

Answers