Partager via


Déplacer un paragraphe d’une présentation vers une autre

Cette rubrique montre comment utiliser les classes du Kit de développement logiciel (SDK) Open XML pour Office pour déplacer un paragraphe d’une présentation à une autre 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 code, le sourceFile paramètre est une chaîne qui représente le chemin du fichier à partir duquel vous souhaitez ouvrir le document.

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 sourceDoc.

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.

Structure du corps du texte d’une forme

Le texte suivant de la spécification ISO/IEC 29500 présente la structure de cet élément.

Cet élément spécifie l’existence du texte qui doit être contenu dans la forme correspondante. L’ensemble du texte visible et des propriétés relatives au texte visible est contenu dans cet élément. Il peut exister plusieurs paragraphes, dans lesquels il peut y avoir plusieurs séquences de texte.

© ISO/IEC 29500 : 2016

Le tableau suivant répertorie les éléments enfants du corps du texte d’une forme, ainsi que la description correspondante.

Élément enfant Description
bodyPr Propriétés du corps
lstStyle Styles de liste du texte
p Paragraphes de texte

Le fragment de schéma XML suivant définit le contenu de cet élément :

    <complexType name="CT_TextBody">
       <sequence>
           <element name="bodyPr" type="CT_TextBodyProperties" minOccurs="1" maxOccurs="1"/>
           <element name="lstStyle" type="CT_TextListStyle" minOccurs="0" maxOccurs="1"/>
           <element name="p" type="CT_TextParagraph" minOccurs="1" maxOccurs="unbounded"/>
       </sequence>
    </complexType>

Fonctionnement de l’exemple de code

Le code de cette rubrique se compose de deux méthodes, MoveParagraphToPresentation et GetFirstSlide. La première méthode accepte deux paramètres de chaîne : un paramètre qui représente le fichier source contenant le paragraphe à déplacer, et un autre paramètre qui représente le fichier cible de destination du paragraphe. La méthode ouvre les deux fichiers de présentation, puis appelle la GetFirstSlide méthode pour obtenir la première diapositive de chaque fichier. Il obtient ensuite la première TextBody forme de chaque diapositive et le premier paragraphe de la forme source. Il exécute un deep clone du paragraphe source, en copiant non seulement l’objet source Paragraph lui-même, mais également tout ce qu’il contient, y compris son texte. Elle insère ensuite le paragraphe cloné dans le fichier cible et supprime le paragraphe source du fichier source, en le remplaçant par un paragraphe d’espace réservé. Enfin, elle enregistre les diapositives modifiées dans les deux présentations.

// Moves a paragraph range in a TextBody shape in the source document
// to another TextBody shape in the target document.
static void MoveParagraphToPresentation(string sourceFile, string targetFile)
{
    // Open the source file as read/write.
    using (PresentationDocument sourceDoc = PresentationDocument.Open(sourceFile, true))
    // </Snippet1
    // Open the target file as read/write.
    using (PresentationDocument targetDoc = PresentationDocument.Open(targetFile, true))
    {
        // Get the first slide in the source presentation.
        SlidePart slide1 = GetFirstSlide(sourceDoc);

        // Get the first TextBody shape in it.
        TextBody textBody1 = slide1.Slide.Descendants<TextBody>().First();

        // Get the first paragraph in the TextBody shape.
        // Note: "Drawing" is the alias of namespace DocumentFormat.OpenXml.Drawing
        Drawing.Paragraph p1 = textBody1.Elements<Drawing.Paragraph>().First();

        // Get the first slide in the target presentation.
        SlidePart slide2 = GetFirstSlide(targetDoc);

        // Get the first TextBody shape in it.
        TextBody textBody2 = slide2.Slide.Descendants<TextBody>().First();

        // Clone the source paragraph and insert the cloned. paragraph into the target TextBody shape.
        // Passing "true" creates a deep clone, which creates a copy of the 
        // Paragraph object and everything directly or indirectly referenced by that object.
        textBody2.Append(p1.CloneNode(true));

        // Remove the source paragraph from the source file.
        textBody1.RemoveChild(p1);

        // Replace the removed paragraph with a placeholder.
        textBody1.AppendChild(new Drawing.Paragraph());
    }
}

La GetFirstSlide méthode prend l’objet PresentationDocument passé, obtient sa partie de présentation, puis obtient l’ID de la première diapositive de sa liste de diapositives. Elle obtient ensuite l’ID de relation de la diapositive, obtient le composant Diapositive à partir de l’ID de relation, puis retourne le composant Diapositive à la méthode appelante.

// Get the slide part of the first slide in the presentation document.
static SlidePart GetFirstSlide(PresentationDocument presentationDocument)
{
    // Get relationship ID of the first slide
    PresentationPart part = presentationDocument.PresentationPart ?? presentationDocument.AddPresentationPart();
    SlideIdList slideIdList = part.Presentation.SlideIdList ?? part.Presentation.AppendChild(new SlideIdList());
    SlideId slideId = part.Presentation.SlideIdList?.GetFirstChild<SlideId>() ?? slideIdList.AppendChild<SlideId>(new SlideId());
    string? relId = slideId.RelationshipId;

    if (relId is null)
    {
        throw new ArgumentNullException(nameof(relId));
    }

    // Get the slide part by the relationship ID.
    SlidePart slidePart = (SlidePart)part.GetPartById(relId);

    return slidePart;
}

Exemple de code

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

// Moves a paragraph range in a TextBody shape in the source document
// to another TextBody shape in the target document.
static void MoveParagraphToPresentation(string sourceFile, string targetFile)
{
    // Open the source file as read/write.
    using (PresentationDocument sourceDoc = PresentationDocument.Open(sourceFile, true))
    // </Snippet1
    // Open the target file as read/write.
    using (PresentationDocument targetDoc = PresentationDocument.Open(targetFile, true))
    {
        // Get the first slide in the source presentation.
        SlidePart slide1 = GetFirstSlide(sourceDoc);

        // Get the first TextBody shape in it.
        TextBody textBody1 = slide1.Slide.Descendants<TextBody>().First();

        // Get the first paragraph in the TextBody shape.
        // Note: "Drawing" is the alias of namespace DocumentFormat.OpenXml.Drawing
        Drawing.Paragraph p1 = textBody1.Elements<Drawing.Paragraph>().First();

        // Get the first slide in the target presentation.
        SlidePart slide2 = GetFirstSlide(targetDoc);

        // Get the first TextBody shape in it.
        TextBody textBody2 = slide2.Slide.Descendants<TextBody>().First();

        // Clone the source paragraph and insert the cloned. paragraph into the target TextBody shape.
        // Passing "true" creates a deep clone, which creates a copy of the 
        // Paragraph object and everything directly or indirectly referenced by that object.
        textBody2.Append(p1.CloneNode(true));

        // Remove the source paragraph from the source file.
        textBody1.RemoveChild(p1);

        // Replace the removed paragraph with a placeholder.
        textBody1.AppendChild(new Drawing.Paragraph());
    }
}
// Get the slide part of the first slide in the presentation document.
static SlidePart GetFirstSlide(PresentationDocument presentationDocument)
{
    // Get relationship ID of the first slide
    PresentationPart part = presentationDocument.PresentationPart ?? presentationDocument.AddPresentationPart();
    SlideIdList slideIdList = part.Presentation.SlideIdList ?? part.Presentation.AppendChild(new SlideIdList());
    SlideId slideId = part.Presentation.SlideIdList?.GetFirstChild<SlideId>() ?? slideIdList.AppendChild<SlideId>(new SlideId());
    string? relId = slideId.RelationshipId;

    if (relId is null)
    {
        throw new ArgumentNullException(nameof(relId));
    }

    // Get the slide part by the relationship ID.
    SlidePart slidePart = (SlidePart)part.GetPartById(relId);

    return slidePart;
}

Voir aussi