Partager via


Insérer une nouvelle diapositive dans une présentation

Cette rubrique montre comment utiliser les classes du Kit de développement logiciel (SDK) Open XML pour insérer une nouvelle diapositive dans une présentation par programmation.

Obtention d’un objet PresentationDocument

Dans le Kit de développement logiciel (SDK) Open XML, la PresentationDocument classe représente un package de document de présentation. Pour utiliser un document de présentation, commencez par créer un instance de la PresentationDocument classe, puis utilisez cette instance. Pour créer la classe instance à partir du document, appelez la Open méthode qui utilise un chemin d’accès de fichier et une valeur booléenne comme deuxième paramètre pour spécifier si un document est modifiable. Pour ouvrir un document en lecture/écriture, spécifiez la valeur true de ce paramètre, comme indiqué dans l’instruction suivante using . Dans ce segment de code, le presentationFile paramètre est une chaîne qui représente le chemin complet du fichier à partir duquel vous souhaitez ouvrir le document.

// Open the source document as read/write. 
using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationFile, true))

Avec v3.0.0+ la Close() méthode a été supprimée au profit de l’instruction using. Cela garantit que la Dispose() méthode est appelée automatiquement lorsque l’accolade fermante est atteinte. Le bloc qui suit l’instruction using établit une étendue pour l’objet créé ou nommé dans l’instruction using , dans ce cas presentationDocument.

Structure de document de présentation de base

La structure de base d’un PresentationML document se compose d’un certain nombre de parties, parmi lesquelles la partie main qui contient la définition de présentation. Le texte suivant de la spécification ISO/IEC 29500 présente la forme globale d’un PresentationML package.

La partie main d’un PresentationML package commence par un élément racine de présentation. Cet élément contient une présentation qui, à son tour, fait référence à une liste de diapositives, à une liste de diapositives master, à une liste de notes master et à un document master liste. La liste des diapositives référence toutes les diapositives de la présentation ; la liste de masques de diapositive référence tous les masques de diapositive utilisés dans la présentation ; le masque de pages de note contient des informations sur la mise en forme des pages de notes et le masque de document décrit comment un document se présente.

Un document à distribuer est un ensemble imprimé de diapositives qui peut être distribué aux personnes de l’audience.

En plus de textes et de graphiques, chaque diapositive peut contenir des commentaires et des notes, peut avoir une disposition et peut faire partie d’une ou plusieurs présentations personnalisées. Un commentaire est une annotation destinée à la personne qui gère le jeu de diapositives de la présentation. Une note est un rappel ou un élément de texte destiné au présentateur ou à l’audience.

Les autres fonctionnalités qu’un PresentationML document peut inclure les suivantes : animation, audio, vidéo et transitions entre les diapositives.

Un PresentationML document n’est pas stocké sous la forme d’un corps volumineux dans une seule partie. Au lieu de cela, les éléments qui implémentent certains groupes de fonctionnalités sont stockés dans des composants distincts. Par exemple, tous les auteurs d’un document sont stockés dans une partie d’auteurs, tandis que chaque diapositive a sa propre partie.

ISO/IEC 29500 : 2016

L’exemple de code XML suivant représente une présentation qui contient deux diapositives ayant les numéros d’identification 267 et 256.

    <p:presentation xmlns:p="…" … > 
       <p:sldMasterIdLst>
          <p:sldMasterId
             xmlns:rel="https://…/relationships" rel:id="rId1"/>
       </p:sldMasterIdLst>
       <p:notesMasterIdLst>
          <p:notesMasterId
             xmlns:rel="https://…/relationships" rel:id="rId4"/>
       </p:notesMasterIdLst>
       <p:handoutMasterIdLst>
          <p:handoutMasterId
             xmlns:rel="https://…/relationships" rel:id="rId5"/>
       </p:handoutMasterIdLst>
       <p:sldIdLst>
          <p:sldId id="267"
             xmlns:rel="https://…/relationships" rel:id="rId2"/>
          <p:sldId id="256"
             xmlns:rel="https://…/relationships" rel:id="rId3"/>
       </p:sldIdLst>
           <p:sldSz cx="9144000" cy="6858000"/>
       <p:notesSz cx="6858000" cy="9144000"/>
    </p:presentation>

À l’aide du Kit de développement logiciel (SDK) Open XML, vous pouvez créer une structure de document et du contenu à l’aide de classes fortement typées qui correspondent aux éléments PresentationML. Vous trouverez ces classes dans l’espace de noms . Le tableau suivant répertorie les noms de classes des classes qui correspondent aux sldéléments , sldLayout, sldMasteret notesMaster .

Élément PresentationML Classe du Kit de développement logiciel (SDK) Open XML Description
<sld/> Slide Diapositive de présentation. Il s’agit de l’élément racine de SlidePart.
<sldLayout/> SlideLayout Mise en page des diapositives. Il s’agit de l’élément racine de SlideLayoutPart.
<sldMaster/> SlideMaster Masque des diapositives. Il s’agit de l’élément racine de SlideMasterPart.
<notesMaster/> NotesMaster Masque des pages de notes (ou handoutMaster). Il s’agit de l’élément racine de NotesMasterPart.

Fonctionnement de l’exemple de code

L’exemple de code se compose de deux surcharges de la InsertNewSlide méthode . La première surcharge accepte trois paramètres : le chemin d’accès complet au fichier de présentation auquel ajouter une diapositive, un entier qui représente la position d’index de base zéro dans la présentation à laquelle ajouter la diapositive, et une chaîne qui représente le titre de la nouvelle diapositive. Il ouvre le fichier de présentation en lecture/écriture, obtient un PresentationDocument objet, puis passe cet objet à la deuxième méthode surchargée InsertNewSlide , qui effectue l’insertion.

// Insert a slide into the specified presentation.
public static void InsertNewSlide(string presentationFile, int position, string slideTitle)
{
    // Open the source document as read/write. 
    using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationFile, true))
    {
        // Pass the source document and the position and title of the slide to be inserted to the next method.
        InsertNewSlide(presentationDocument, position, slideTitle);
    }
}

La deuxième méthode surchargée InsertNewSlide crée un Slide objet, définit ses propriétés, puis l’insère dans l’ordre des diapositives de la présentation. La première section de la méthode crée la diapositive et définit ses propriétés.

// Insert the specified slide into the presentation at the specified position.
public static SlidePart InsertNewSlide(PresentationDocument presentationDocument, int position, string slideTitle)
{
    PresentationPart? presentationPart = presentationDocument.PresentationPart;

    // Verify that the presentation is not empty.
    if (presentationPart is null)
    {
        throw new InvalidOperationException("The presentation document is empty.");
    }

    // Declare and instantiate a new slide.
    Slide slide = new Slide(new CommonSlideData(new ShapeTree()));
    uint drawingObjectId = 1;

    // Construct the slide content.            
    // Specify the non-visual properties of the new slide.
    CommonSlideData commonSlideData = slide.CommonSlideData ?? slide.AppendChild(new CommonSlideData());
    ShapeTree shapeTree = commonSlideData.ShapeTree ?? commonSlideData.AppendChild(new ShapeTree());
    NonVisualGroupShapeProperties nonVisualProperties = shapeTree.AppendChild(new NonVisualGroupShapeProperties());
    nonVisualProperties.NonVisualDrawingProperties = new NonVisualDrawingProperties() { Id = 1, Name = "" };
    nonVisualProperties.NonVisualGroupShapeDrawingProperties = new NonVisualGroupShapeDrawingProperties();
    nonVisualProperties.ApplicationNonVisualDrawingProperties = new ApplicationNonVisualDrawingProperties();

    // Specify the group shape properties of the new slide.
    shapeTree.AppendChild(new GroupShapeProperties());

La section suivante de la deuxième méthode surchargée InsertNewSlide ajoute une forme de titre à la diapositive et définit ses propriétés, y compris son texte.

// Declare and instantiate the title shape of the new slide.
Shape titleShape = shapeTree.AppendChild(new Shape());

drawingObjectId++;

// Specify the required shape properties for the title shape. 
titleShape.NonVisualShapeProperties = new NonVisualShapeProperties
    (new NonVisualDrawingProperties() { Id = drawingObjectId, Name = "Title" },
    new NonVisualShapeDrawingProperties(new Drawing.ShapeLocks() { NoGrouping = true }),
    new ApplicationNonVisualDrawingProperties(new PlaceholderShape() { Type = PlaceholderValues.Title }));
titleShape.ShapeProperties = new ShapeProperties();

// Specify the text of the title shape.
titleShape.TextBody = new TextBody(new Drawing.BodyProperties(),
        new Drawing.ListStyle(),
        new Drawing.Paragraph(new Drawing.Run(new Drawing.Text() { Text = slideTitle })));

La section suivante de la deuxième méthode surchargée InsertNewSlide ajoute une forme de corps à la diapositive et définit ses propriétés, y compris son texte.

// Declare and instantiate the body shape of the new slide.
Shape bodyShape = shapeTree.AppendChild(new Shape());
drawingObjectId++;

// Specify the required shape properties for the body shape.
bodyShape.NonVisualShapeProperties = new NonVisualShapeProperties(new NonVisualDrawingProperties() { Id = drawingObjectId, Name = "Content Placeholder" },
        new NonVisualShapeDrawingProperties(new Drawing.ShapeLocks() { NoGrouping = true }),
        new ApplicationNonVisualDrawingProperties(new PlaceholderShape() { Index = 1 }));
bodyShape.ShapeProperties = new ShapeProperties();

// Specify the text of the body shape.
bodyShape.TextBody = new TextBody(new Drawing.BodyProperties(),
        new Drawing.ListStyle(),
        new Drawing.Paragraph());

La dernière section de la deuxième méthode surchargée InsertNewSlide crée un composant de diapositive, recherche la position d’index spécifiée où insérer la diapositive, puis l’insère et affecte la nouvelle diapositive au nouveau composant de diapositive.

// Create the slide part for the new slide.
SlidePart slidePart = presentationPart.AddNewPart<SlidePart>();

// Assign the new slide to the new slide part
slidePart.Slide = slide;

// Modify the slide ID list in the presentation part.
// The slide ID list should not be null.
SlideIdList? slideIdList = presentationPart.Presentation.SlideIdList;

// Find the highest slide ID in the current list.
uint maxSlideId = 1;
SlideId? prevSlideId = null;

OpenXmlElementList slideIds = slideIdList?.ChildElements ?? default;

foreach (SlideId slideId in slideIds)
{
    if (slideId.Id is not null && slideId.Id > maxSlideId)
    {
        maxSlideId = slideId.Id;
    }

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

}

maxSlideId++;

// Get the ID of the previous slide.
SlidePart lastSlidePart;

if (prevSlideId is not null && prevSlideId.RelationshipId is not null)
{
    lastSlidePart = (SlidePart)presentationPart.GetPartById(prevSlideId.RelationshipId!);
}
else
{
    string? firstRelId = ((SlideId)slideIds[0]).RelationshipId;
    // If the first slide does not contain a relationship ID, throw an exception.
    if (firstRelId is null)
    {
        throw new ArgumentNullException(nameof(firstRelId));
    }

    lastSlidePart = (SlidePart)presentationPart.GetPartById(firstRelId);
}

// Use the same slide layout as that of the previous slide.
if (lastSlidePart.SlideLayoutPart is not null)
{
    slidePart.AddPart(lastSlidePart.SlideLayoutPart);
}

// Insert the new slide into the slide list after the previous slide.
SlideId newSlideId = slideIdList!.InsertAfter(new SlideId(), prevSlideId);
newSlideId.Id = maxSlideId;
newSlideId.RelationshipId = presentationPart.GetIdOfPart(slidePart);

Exemple de code

Voici un exemple de code complet en C# et Visual Basic.

// Insert a slide into the specified presentation.
public static void InsertNewSlide(string presentationFile, int position, string slideTitle)
{
    // Open the source document as read/write. 
    using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationFile, true))
    {
        // Pass the source document and the position and title of the slide to be inserted to the next method.
        InsertNewSlide(presentationDocument, position, slideTitle);
    }
}
// Insert the specified slide into the presentation at the specified position.
public static SlidePart InsertNewSlide(PresentationDocument presentationDocument, int position, string slideTitle)
{
    PresentationPart? presentationPart = presentationDocument.PresentationPart;

    // Verify that the presentation is not empty.
    if (presentationPart is null)
    {
        throw new InvalidOperationException("The presentation document is empty.");
    }

    // Declare and instantiate a new slide.
    Slide slide = new Slide(new CommonSlideData(new ShapeTree()));
    uint drawingObjectId = 1;

    // Construct the slide content.            
    // Specify the non-visual properties of the new slide.
    CommonSlideData commonSlideData = slide.CommonSlideData ?? slide.AppendChild(new CommonSlideData());
    ShapeTree shapeTree = commonSlideData.ShapeTree ?? commonSlideData.AppendChild(new ShapeTree());
    NonVisualGroupShapeProperties nonVisualProperties = shapeTree.AppendChild(new NonVisualGroupShapeProperties());
    nonVisualProperties.NonVisualDrawingProperties = new NonVisualDrawingProperties() { Id = 1, Name = "" };
    nonVisualProperties.NonVisualGroupShapeDrawingProperties = new NonVisualGroupShapeDrawingProperties();
    nonVisualProperties.ApplicationNonVisualDrawingProperties = new ApplicationNonVisualDrawingProperties();

    // Specify the group shape properties of the new slide.
    shapeTree.AppendChild(new GroupShapeProperties());
    // Declare and instantiate the title shape of the new slide.
    Shape titleShape = shapeTree.AppendChild(new Shape());

    drawingObjectId++;

    // Specify the required shape properties for the title shape. 
    titleShape.NonVisualShapeProperties = new NonVisualShapeProperties
        (new NonVisualDrawingProperties() { Id = drawingObjectId, Name = "Title" },
        new NonVisualShapeDrawingProperties(new Drawing.ShapeLocks() { NoGrouping = true }),
        new ApplicationNonVisualDrawingProperties(new PlaceholderShape() { Type = PlaceholderValues.Title }));
    titleShape.ShapeProperties = new ShapeProperties();

    // Specify the text of the title shape.
    titleShape.TextBody = new TextBody(new Drawing.BodyProperties(),
            new Drawing.ListStyle(),
            new Drawing.Paragraph(new Drawing.Run(new Drawing.Text() { Text = slideTitle })));
    // Declare and instantiate the body shape of the new slide.
    Shape bodyShape = shapeTree.AppendChild(new Shape());
    drawingObjectId++;

    // Specify the required shape properties for the body shape.
    bodyShape.NonVisualShapeProperties = new NonVisualShapeProperties(new NonVisualDrawingProperties() { Id = drawingObjectId, Name = "Content Placeholder" },
            new NonVisualShapeDrawingProperties(new Drawing.ShapeLocks() { NoGrouping = true }),
            new ApplicationNonVisualDrawingProperties(new PlaceholderShape() { Index = 1 }));
    bodyShape.ShapeProperties = new ShapeProperties();

    // Specify the text of the body shape.
    bodyShape.TextBody = new TextBody(new Drawing.BodyProperties(),
            new Drawing.ListStyle(),
            new Drawing.Paragraph());
    // Create the slide part for the new slide.
    SlidePart slidePart = presentationPart.AddNewPart<SlidePart>();
    
    // Assign the new slide to the new slide part
    slidePart.Slide = slide;

    // Modify the slide ID list in the presentation part.
    // The slide ID list should not be null.
    SlideIdList? slideIdList = presentationPart.Presentation.SlideIdList;

    // Find the highest slide ID in the current list.
    uint maxSlideId = 1;
    SlideId? prevSlideId = null;

    OpenXmlElementList slideIds = slideIdList?.ChildElements ?? default;

    foreach (SlideId slideId in slideIds)
    {
        if (slideId.Id is not null && slideId.Id > maxSlideId)
        {
            maxSlideId = slideId.Id;
        }

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

    }

    maxSlideId++;

    // Get the ID of the previous slide.
    SlidePart lastSlidePart;

    if (prevSlideId is not null && prevSlideId.RelationshipId is not null)
    {
        lastSlidePart = (SlidePart)presentationPart.GetPartById(prevSlideId.RelationshipId!);
    }
    else
    {
        string? firstRelId = ((SlideId)slideIds[0]).RelationshipId;
        // If the first slide does not contain a relationship ID, throw an exception.
        if (firstRelId is null)
        {
            throw new ArgumentNullException(nameof(firstRelId));
        }

        lastSlidePart = (SlidePart)presentationPart.GetPartById(firstRelId);
    }

    // Use the same slide layout as that of the previous slide.
    if (lastSlidePart.SlideLayoutPart is not null)
    {
        slidePart.AddPart(lastSlidePart.SlideLayoutPart);
    }

    // Insert the new slide into the slide list after the previous slide.
    SlideId newSlideId = slideIdList!.InsertAfter(new SlideId(), prevSlideId);
    newSlideId.Id = maxSlideId;
    newSlideId.RelationshipId = presentationPart.GetIdOfPart(slidePart);

    return slidePart;
}

Voir aussi