C#-OpenXML SDK 2.5-使用包含图像的布局从幻灯片母版插入新幻灯片 [英] C# - OpenXML SDK 2.5 - Insert New Slide from Slide Masters with the layout that contains images

查看:157
本文介绍了C#-OpenXML SDK 2.5-使用包含图像的布局从幻灯片母版插入新幻灯片的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用了此[ https://codingthedocument.wordpress.com/author/agschwantes/] 在OpenXML 2.5 SDK的帮助下创建我的新幻灯片. 我设计并使用了自己的Slide Master来创建新的幻灯片.我的幻灯片母版包括一些带有图像的布局和一些没有图像的布局.

I used this [https://codingthedocument.wordpress.com/author/agschwantes/] to create my new slides with the help of the OpenXML 2.5 SDK. I designed and used my own Slide Master to create a new slide. My Slide Master includes some layouts with images and some layouts without images.

如果我从我的主版式创建幻灯片时没有图像,则一切正常.如果我用包含图像的布局创建幻灯片,则在每个固定图像的顶部都有正确的布局,但是还有一个与固定图像重叠的可移动图像,因此不需要多余的固定图像副本,我不需要在我新创建的幻灯片中.

If I create a slide from my Master Layout without images, everything works fine. If I create a slide with the layout, that contains images, I get the right layout BUT on top of every fixed images there is another movable image overlapping the fixed one, so there are unnecessary duplicates of fixed images, that I don't need in my new created slide.

我该如何解决这个问题?

How can I solve this problem?

我的代码如下:

       public static void InsertNewSlide(string presentationFile, int position, string layoutName)
      {
        using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationFile, true))
        {

            InsertNewSlide(presentationDocument, position, layoutName);
        }
      }

    public static void InsertNewSlide(PresentationDocument presentationDocument, int position, string layoutName)
    {
        PresentationPart presentationPart = presentationDocument.PresentationPart;

        OpenXML.Slide slide = new OpenXML.Slide(new CommonSlideData(new ShapeTree()));

        SlidePart slidePart = presentationPart.AddNewPart<SlidePart>();

        slide.Save(slidePart);

        SlideMasterPart slideMasterPart = presentationPart.SlideMasterParts.First();

        SlideLayoutPart slideLayoutPart = slideMasterPart.SlideLayoutParts.SingleOrDefault(sl => sl.SlideLayout.CommonSlideData.Name.Value.Equals(layoutName, StringComparison.OrdinalIgnoreCase));

        slidePart.AddPart<SlideLayoutPart>(slideLayoutPart);

        slidePart.Slide.CommonSlideData = (CommonSlideData)slideMasterPart.SlideLayoutParts.SingleOrDefault(sl => sl.SlideLayout.CommonSlideData.Name.Value.Equals(layoutName)).SlideLayout.CommonSlideData.Clone();

        using (Stream stream = slideLayoutPart.GetStream())
        {
            slidePart.SlideLayoutPart.FeedData(stream);

        }

        foreach (ImagePart iPart in slideLayoutPart.ImageParts)
        {
             ImagePart newImagePart = slidePart.AddImagePart(iPart.ContentType, slideLayoutPart.GetIdOfPart(iPart));
                                                        newImagePart.FeedData(iPart.GetStream());
        }

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

            position--;
            if (position == 0)
            {
                prevSlideId = slideId;
            }

        }
        maxSlideId++;
        SlideId newSlideId = slideIdList.InsertAfter(new SlideId(), prevSlideId);
        newSlideId.Id = maxSlideId;
        newSlideId.RelationshipId = presentationPart.GetIdOfPart(slidePart);

        presentationPart.Presentation.Save();
    }

}

推荐答案

几年后,但是对其他人有所帮助-无需将不提供占位符功能的节点复制到基于主幻灯片模板的新幻灯片上(包括图片).

Years later, but to help others - there is no need to copy nodes which are not serving a placeholder function to the new slide being based on the master slide template (including images).

using (Stream stream = slideLayoutPart.GetStream())
{
    slidePart.SlideLayoutPart.FeedData(stream);

显然假设您没有在1个工作流中添加一张幻灯片(也就是说,您有用于读取和写入的单独流),并且等效行

obviously assumes you are not adding a slide within 1 working stream (that is you have separate streams for reading and writing), and the equivalent line

slidePart.Slide.CommonSlideData = (CommonSlideData)layoutPart.SlideLayout.CommonSlideData.Clone();

这两个代码行都将所有主数据复制为新幻灯片上的覆盖图.例如,运行上述答案中的代码块之一,在演示文稿管理器中打开生成的.pptx文件,然后删除看到的任何形状-您会注意到每个项目都位于同一副本的顶部(主幻灯片)版本),则无法删除.因此,此方法不必要地使文件过大,并使.pptx杂乱无章,而不是最终用户所预期的那样.

Both of these lines of code copy all the master data as an overlay onto the new slide . As an example, run one of the blocks of code from the answers above, open the resulting .pptx file in a presentation manager and delete whatever shapes you see - you will note each item is sitting on top of an identical copy (the master slide version) which you cannot delete. This method therefore bloats the file unnecessarily and makes working with the .pptx messy and not as predicted for the end user.

下面的代码适用于图像

public static SlidePart AppendNewSlide(PresentationPart presentationPart, SlideLayoutPart masterLayoutPart, out IEnumerable<Shape> placeholderShapes)
{
    Slide clonedSlide = new Slide() {
        ColorMapOverride = new ColorMapOverride {
            MasterColorMapping = new Draw.MasterColorMapping()
        }
    };

    SlidePart clonedSlidePart = presentationPart.AddNewPart<SlidePart>();
    clonedSlidePart.Slide = clonedSlide;
    clonedSlidePart.AddPart(masterLayoutPart);
    clonedSlide.Save(clonedSlidePart);

    var masterShapeTree = masterLayoutPart.SlideLayout.CommonSlideData.ShapeTree;

    placeholderShapes = (from s in masterShapeTree.ChildElements<Shape>()
                           where s.NonVisualShapeProperties.OfType<ApplicationNonVisualDrawingProperties>().Any(anvdp=>anvdp.PlaceholderShape != null)
                           select new Shape()
                           {
                               NonVisualShapeProperties = (NonVisualShapeProperties)s.NonVisualShapeProperties.CloneNode(true),
                               TextBody = new TextBody(s.TextBody.ChildElements<Draw.Paragraph>().Select(p => p.CloneNode(true))) {
                                   BodyProperties = new Draw.BodyProperties(),
                                   ListStyle = new Draw.ListStyle()
                               },
                               ShapeProperties = new ShapeProperties()
                           }).ToList();

    clonedSlide.CommonSlideData = new CommonSlideData
    {
        ShapeTree = new ShapeTree(placeholderShapes) {
            GroupShapeProperties = (GroupShapeProperties)masterShapeTree.GroupShapeProperties.CloneNode(true),
            NonVisualGroupShapeProperties = (NonVisualGroupShapeProperties)masterShapeTree.NonVisualGroupShapeProperties.CloneNode(true)
        }
    };

    SlideIdList slideIdList = presentationPart.Presentation.SlideIdList;

    // Find the highest slide ID in the current list.
    uint maxSlideId = slideIdList.Max(c=>(uint?)((SlideId)c).Id) ?? 256;

    // Insert the new slide into the slide list after the previous slide.
    slideIdList.Append(new SlideId() {
        Id = ++maxSlideId,
        RelationshipId = presentationPart.GetIdOfPart(clonedSlidePart)
    });
    //presentationPart.Presentation.Save();

    return clonedSlidePart;
}

//helper method used above in separate static class
public static IEnumerable<T> ChildElements<T>(this OpenXmlElement el) where T: OpenXmlElement
{
    if (el.HasChildren)
    {
        var child = el.GetFirstChild<T>();
        while (child != null)
        {
            yield return child;
            child = child.NextSibling<T>();
        }
    }
}

out参数placeholderShapes假设在基于主模板创建新幻灯片后,开发人员希望更改某些占位符内容

the out parameter placeholderShapes is assuming after creating a new slide based on a master template that the developer will wish to alter some of the placeholder content

这篇关于C#-OpenXML SDK 2.5-使用包含图像的布局从幻灯片母版插入新幻灯片的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆