【问题标题】:Corrupted PPTX file when using OpenXML to create PowerPoint presentation使用 OpenXML 创建 PowerPoint 演示文稿时损坏的 PPTX 文件
【发布时间】:2013-03-24 03:38:14
【问题描述】:

**重要提示:代码块后回答的问题**

平台: C#、OpenXML SDK (2.5)、.NET 4.0

我正在努力实现的目标

我一直在尝试从我的数据库中的一些数据和图像生成一个 pptx 演示文稿。 任何生成的文件都会损坏,但它确实通过了 OOXML 验证。我真的不知道我还能做什么。

我已经尝试过的

我尝试删除图像、文本,然后我评论了删除第一张(模板)幻灯片的代码,但没有改变我的最终结果:文件损坏。

错误

当我尝试打开文件时:“PowerPoint 无法显示文件“filename.pptx”中幻灯片上的某些文本、图像或对象,因为它们已损坏。 受影响的幻灯片已被演示文稿中的空白幻灯片替换,并且无法恢复丢失的信息。要确保文件可以在早期版本的 PowerPoint 中打开,请使用“另存为”命令(“文件”菜单)并使用相同名称或新名称保存文件。

代码

这是我用来生成 PPTX 的代码:

void GenerateSlides(string fullPath, string path, IEnumerable<Data> data)
    {
        var slidePath = fullPath;

        if (!Directory.Exists(path))
            Directory.CreateDirectory(path);

        // Copy the template file to generate new slides
        File.Copy(string.Format("{0}{1}", path, "TemplateTF.pptx"), slidePath, true);

        using (var presentationDocument = PresentationDocument.Open(slidePath, true))
        {
            var presentationPart = presentationDocument.PresentationPart;
            var slideTemplate = (SlidePart)presentationPart.GetPartById("rId2");

            // Recover the data to fullfill the slidepart
            int i = 1;

            foreach (var singleData in data)
            {
                (...)

                // Creates the new image
                var newSlide = CloneSlidePart(presentationPart, slideTemplate);
                var imgId = "rIdImg" + i;
                var imagePart = newSlide.AddImagePart(ImagePartType.Jpeg, imgId);
                var stream = new MemoryStream();
                using (var file = File.Open(string.Format("{0}{1}"
                    , WebConfigurationManager.AppSettings["pathImages"]
                    , singleData.ImageName), FileMode.Open))
                {
                    var buffer = new byte[file.Length];
                    file.Read(buffer, 0, (int)file.Length);
                    stream.Write(buffer, 0, buffer.Length);
                    imagePart.FeedData(new MemoryStream(buffer));
                }
                // Important method to swap the original image
                SwapPhoto(newSlide, imgId);
                i++;

                InsertContent(newSlide, (...));
                SwapPhoto(newSlide, imgId);
                newSlide.Slide.Save();
            }

            DeleteTemplateSlide(presentationPart, slideTemplate);
            presentationPart.Presentation.Save();
        }
    }

void SwapPhoto(SlidePart slidePart, string imgId)
    {
        var blip = slidePart.Slide.Descendants<Drawing.Blip>().First();
        blip.Embed = imgId;
        slidePart.Slide.Save();
    }

void DeleteTemplateSlide(PresentationPart presentationPart, SlidePart slideTemplate)
    {
        var slideIdList = presentationPart.Presentation.SlideIdList;
        foreach (SlideId slideId in slideIdList.ChildElements)
        {
            if (slideId.RelationshipId.Value.Equals("rId2"))
            {
                slideIdList.RemoveChild(slideId);
            }
        }
        presentationPart.DeletePart(slideTemplate);
    }

SlidePart CloneSlidePart(PresentationPart presentationPart, SlidePart slideTemplate)
    {
        var newSlidePart = presentationPart.AddNewPart<SlidePart>("newSlide" + i);
        i++;
        newSlidePart.FeedData(slideTemplate.GetStream(FileMode.Open));
        newSlidePart.AddPart(slideTemplate.SlideLayoutPart);

        var slideIdList = presentationPart.Presentation.SlideIdList;

        uint maxSlideId = 1;
        SlideId prevSlideId = null;
        foreach (SlideId slideId in slideIdList.ChildElements)
        {
            if (slideId.Id > maxSlideId)
            {
                maxSlideId = slideId.Id;
                prevSlideId = slideId;
            }
        }
        maxSlideId++;

        var newSlideId = slideIdList.InsertAfter(new SlideId(), prevSlideId);
        newSlideId.Id = maxSlideId;
        newSlideId.RelationshipId = presentationPart.GetIdOfPart(newSlidePart);

        return newSlidePart;
    }

void InsertContent(SlidePart slidePart, (...))
    {
        SwapPlaceholderText(slidePart, "Title", "ReplacementString1");
        SwapPlaceholderText(slidePart, "Text", "ReplacementString2");
    }

    void SwapPlaceholderText(SlidePart slidePart, string placeholder, string value)
    {
        var textList = slidePart.Slide.Descendants<Drawing.Text>().Where(
           t => t.Text.Equals(placeholder)).ToList();

        foreach (Drawing.Text text in textList)
        {
            text.Text = value;
        }
    }



回答

好的,我意识到 MS Office 版本可以有多么不同。

a)如果我尝试使用 Office 2013 打开 .pptx 文件:错误消息 + 完美打开,没有徽标图像或幻灯片部分显示任何附加信息

b)如果我尝试使用 Office 2007 打开 .pptx 文件:错误消息 + 空白幻灯片,根本没有信息

c)如果我尝试使用 Office 2010 打开 .pptx 文件:错误消息 + 空白幻灯片以及我可能拥有的最重要信息:徽标位置的图标损坏!!!

我从模板中删除了徽标图像,瞧,文件已完美生成。现在,如果我真的需要添加徽标图像,我可以通过编程方式完成。

谢谢!在尝试了解到底发生了什么一周后,我的一位好朋友使用 Office 2010 打开了该文件,然后我发现原来的模板文件中的徽标图像已损坏。

谢谢:)

【问题讨论】:

  • (...) 中的 foreach 行不是有效的 C#。
  • 谢谢 :) 这只是我用来替换幻灯片中的一些文本的文本数据。

标签: c# powerpoint openxml


【解决方案1】:

好的,我意识到 MS Office 版本可以有多么不同。

a) 如果我尝试使用 Office 2013 打开 .pptx 文件:错误消息 + 完美打开,没有徽标图像或幻灯片部分显示任何附加信息 b) 如果我尝试使用 Office 2007 打开 .pptx 文件:错误消息 + 空白幻灯片,根本没有信息 c) 如果我尝试使用 Office 2010 打开 .pptx 文件:错误消息 + 空白幻灯片以及我可能拥有的最重要信息:徽标位置的图标损坏!!!

我从模板中删除了徽标图像,瞧,文件已完美生成。现在,如果我真的需要添加徽标图像,我可以通过编程方式完成。

谢谢!在尝试了解到底发生了什么一周后,我的一个朋友使用 Office 2010 打开了该文件,然后我发现原来的模板文件中的徽标图像已损坏。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-05
    • 2015-11-17
    • 2010-10-03
    • 1970-01-01
    相关资源
    最近更新 更多