【问题标题】:Programmatically generated PowerPoint presentations break PowerPoint 2013以编程方式生成的 PowerPoint 演示文稿打破 PowerPoint 2013
【发布时间】:2014-12-10 16:55:19
【问题描述】:

我正在尝试从不同来源生成演示文稿。基本上,我有大约 200 张幻灯片来自一些 PowerPoint 演示文稿。 为了实现这一点,我正在使用 OpenXml Sdk。 程序流程如下:

  • 打开模板演示文稿
  • 打开新的演示文稿
  • 将第二个演示文稿中的幻灯片合并到模板演示文稿中

最后,我将新的演示文稿保存到磁盘。 尝试使用 PowerPoint 2013 打开它会破坏它,并显示以下信息: 问题签名:

Problem Event Name: APPCRASH
Application Name:   POWERPNT.EXE
Application Version:    15.0.4454.1000
Application Timestamp:  509a3abf
Fault Module Name:  oart.dll
Fault Module Version:   15.0.4605.1000
Fault Module Timestamp: 531f9b2a
Exception Code: c00000fd
Exception Offset:   00003051
OS Version: 6.2.9200.2.0.0.272.7
Locale ID:  1033

有关问题的其他信息:

LCID:   1033
skulcid:    1033

使用PowerPoint 2010 打开它就可以了。没有问题。

这是代码:

private static void MergePresentation(string generatedPresentation, string presentationToBeMerged)
{
    try
    {
        int id = 0;

        // Open the destination presentation.
        using (PresentationDocument generatedPresentationDeck = PresentationDocument.Open(generatedPresentation, true))
        {
            PresentationPart generatedPresentationPart = generatedPresentationDeck.PresentationPart;

            // If the merged presentation does not have a SlideIdList 
            // element yet, add it.
            if (generatedPresentationPart.Presentation.SlideIdList == null)
            {
                generatedPresentationPart.Presentation.SlideIdList = new SlideIdList();
            }

            // Open the source presentation. This will throw an exception if
            // the source presentation does not exist.
            using (PresentationDocument mySourceDeck = PresentationDocument.Open(presentationToBeMerged, false))
            {
                PresentationPart sourcePresPart = mySourceDeck.PresentationPart;

                // Get unique ids for the slide master and slide lists
                // for use later.
                _uniqueId = GetMaxSlideMasterId(generatedPresentationPart.Presentation.SlideMasterIdList);

                uint maxSlideId = GetMaxSlideId(generatedPresentationPart.Presentation.SlideIdList);

                // Copy each slide in the source presentation, in order, to 
                // the destination presentation.
                foreach (SlideId slideId in sourcePresPart.Presentation.SlideIdList)
                {
                    SlidePart sp;
                    SlidePart destSp;
                    SlideMasterPart destMasterPart;
                    string relId;
                    SlideMasterId newSlideMasterId;
                    SlideId newSlideId;

                    // Create a unique relationship id.
                    id++;
                    sp = (SlidePart)sourcePresPart.GetPartById(slideId.RelationshipId);

                    //sp.Slide.Transition.Remove();

                    relId = Path.GetFileNameWithoutExtension(presentationToBeMerged).Replace(" ", "_") + id;

                    // Add the slide part to the destination presentation.
                    destSp = generatedPresentationPart.AddPart<SlidePart>(sp, relId);

                    // The slide master part was added. Make sure the
                    // relationship between the main presentation part and
                    // the slide master part is in place.
                    destMasterPart = destSp.SlideLayoutPart.SlideMasterPart;
                    generatedPresentationPart.AddPart(destMasterPart);

                    // Add the slide master id to the slide master id list.
                    _uniqueId++;
                    newSlideMasterId = new SlideMasterId();

                    newSlideMasterId.RelationshipId = generatedPresentationPart.GetIdOfPart(destMasterPart);

                    newSlideMasterId.Id = _uniqueId;

                    generatedPresentationPart.Presentation.SlideMasterIdList.Append(newSlideMasterId);

                    // Add the slide id to the slide id list.
                    maxSlideId++;
                    newSlideId = new SlideId();
                    newSlideId.RelationshipId = relId;
                    newSlideId.Id = maxSlideId;

                    generatedPresentationPart.Presentation.SlideIdList.Append(newSlideId);
                }

                // Make sure that all slide layout ids are unique.
                FixSlideLayoutIds(generatedPresentationPart);
            }

            // Save the changes to the destination deck.
            generatedPresentationPart.Presentation.Save();
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

/// <summary>
/// Find the maximum value of ID of all slide masters
/// </summary>
/// <param name="slideMasterIdList" />
/// <returns>
private static uint GetMaxSlideMasterId(SlideMasterIdList slideMasterIdList)
{
    // Slide master identifiers have a minimum value of greater than
    // or equal to 2147483648. 
    uint max = 2147483648;

    if (slideMasterIdList != null)
        // Get the maximum id value from the current set of children.
        foreach (SlideMasterId child in
            slideMasterIdList.Elements<SlideMasterId>())
        {
            uint id = child.Id;

            if (id > max)
                max = id;
        }

    return max;
}

/// <summary>
/// Find the maximum ID of all slides
/// </summary>
/// <param name="slideIdList" />
/// <returns>
private static uint GetMaxSlideId(SlideIdList slideIdList)
{
    // Slide identifiers have a minimum value of greater than or
    // equal to 256 and a maximum value of less than 2147483648. 
    uint max = 256;

    if (slideIdList != null)
        // Get the maximum id value from the current set of children.
        foreach (SlideId child in slideIdList.Elements<SlideId>())
        {
            uint id = child.Id;

            if (id > max)
                max = id;
        }

    return max;
}

/// <summary>
/// Fix the IDs of all slide layouts by making sure that all the slide layout IDs in the
/// destination slide are unique.
/// </summary>
/// <param name="presPart" />
private static void FixSlideLayoutIds(PresentationPart presPart)
{
    // Make sure that all slide layouts have unique ids.
    foreach (SlideMasterPart slideMasterPart in presPart.SlideMasterParts)
    {
        foreach (SlideLayoutId slideLayoutId in slideMasterPart.SlideMaster.SlideLayoutIdList)
        {
            _uniqueId++;
            slideLayoutId.Id = (uint)_uniqueId;
        }

        slideMasterPart.SlideMaster.Save();
    }
}

我调用Merge函数的方式是:

string templateFilePath = @"C:\Users\mm\Desktop\testing pp\Presentation1.pptx";
string newFilePath = @"C:\Users\mm\Desktop\testing pp\Generated Presentation-105.pptx";
MergePresentation(templateFilePath, newFilePath);

有什么想法吗?

谢谢

【问题讨论】:

    标签: c# powerpoint openxml-sdk


    【解决方案1】:

    我已经设法找到了解决方案。 在这里发布它以防其他人遇到此问题。

    我在生成的演示文稿上使用过 OpenXml Sdk Validator,发现以下错误: 该元素有意外的子元素'http://schemas.openxmlformats.org/presentationml/2006/main:notesMasterIdLst'

    这将我的注意力引向幻灯片中的注释。删除它们解决了问题,一切正常。

    删除注释的代码(即使您在 PP 中打开演示文稿时看不到任何注释):

     public static void RemoveNotesFromDoc(string docPath)
        {
            try
            {
                using (PresentationDocument pDoc =
                    PresentationDocument.Open(docPath, true))
                {
                    foreach (var slide in pDoc.PresentationPart.SlideParts)
                    {
                        NotesSlidePart notes = slide.NotesSlidePart;
    
    
                        if (notes != null)
                        {
                            slide.DeletePart(slide.GetIdOfPart(slide.NotesSlidePart));
                        }
                    }
                }
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2010-10-03
      • 1970-01-01
      • 2017-04-22
      • 1970-01-01
      • 2013-12-14
      • 1970-01-01
      • 2011-04-02
      • 2015-12-28
      • 2023-03-29
      相关资源
      最近更新 更多