Compartilhar via


Adicionar um comentário a um slide de uma apresentação

Este tópico mostra como usar as classes no SDK Do Open XML para Office para adicionar um comentário ao primeiro slide em uma apresentação de forma programática.

Estrutura básica do documento de apresentação

A estrutura básica do documento de um documento PresentationML consiste em várias partes, entre elas a main parte que contém a definição de apresentação. O texto a seguir da especificação ISO/IEC 29500 apresenta a forma geral de um pacote PresentationML .

A main parte de um pacote PresentationML começa com um elemento raiz de apresentação. Esse elemento contém uma apresentação que, por sua vez, se refere a uma lista de slides, uma lista de master de slides, uma lista de master de anotações e uma lista de master de apostila. A lista de slides refere-se a todos os slides na apresentação; A lista de master de slides refere-se a todos os mestres de slides usados na apresentação; as anotações master contém informações sobre a formatação de páginas de anotações; e a apostila master descreve como uma apostila parece.

Uma apostila é um conjunto impresso de slides que pode ser fornecido a uma audiência.

Além de texto e gráficos, cada slide pode conter comentários e anotações, pode ter um layout e pode fazer parte de uma ou mais apresentações personalizadas. Um comentário é uma anotação destinada à pessoa que mantém o deck de slides de apresentação. Uma nota é um lembrete ou um pedaço de texto destinado ao apresentador ou ao público-alvo.

Outros recursos que um documento PresentationML pode incluir o seguinte: animação, áudio, vídeo e transições entre slides.

Um documento PresentationML não é armazenado como um corpo grande em uma única parte. Em vez disso, os elementos que implementam determinados agrupamentos de funcionalidade são armazenados em partes separadas. Por exemplo, todos os comentários em um documento são armazenados em uma parte de comentário, enquanto cada slide tem sua própria parte.

© ISO/IEC29500: 2008.

O exemplo de código XML a seguir representa uma apresentação que contém dois slides denotados pelas IDs 267 e 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>

Usando o SDK do Open XML, você pode criar estrutura de documentos e conteúdo usando classes fortemente tipdas que correspondem a elementos PresentationML. Você pode encontrar essas classes no namespace DocumentFormat.OpenXml.Presentation . A tabela a seguir lista os nomes de classe das classes que correspondem aos elementos sld, sldLayout, sldMaster e notesMaster .

Elemento PresentationML Classe SDK Open XML Descrição
Sld Slide Slide de Apresentação. É o elemento raiz do SlidePart.
sldLayout SlideLayout Layout do Slide. É o elemento raiz do SlideLayoutPart.
sldMaster SlideMaster Mestre de Slides. É o elemento raiz do SlideMasterPart.
notesMaster NotesMaster Mestre de Anotações (ou handoutMaster). É o elemento raiz do NotesMasterPart.

A estrutura do elemento Comment

Um comentário é uma nota de texto anexada a um slide, com o objetivo principal de permitir que os leitores de uma apresentação forneçam comentários ao autor da apresentação. Cada comentário contém uma cadeia de texto não formatada e informações sobre seu autor e é anexado a um local específico em um slide. Os comentários podem ser visíveis durante a edição da apresentação, mas não aparecem quando uma apresentação de slides é fornecida. O aplicativo de exibição decide quando exibir comentários e determina sua aparência visual.

O elemento XML a seguir especifica um único comentário anexado a um slide. Ele contém o texto do comentário (texto), sua posição no slide (pos) e atributos referentes a seu autor (authorId), data e hora (dt) e índice de comentários (idx).

    <p:cm authorId="0" dt="2006-08-28T17:26:44.129" idx="1">
        <p:pos x="10" y="10"/>
        <p:text>Add diagram to clarify.</p:text>
    </p:cm>

A tabela a seguir contém as definições dos membros e atributos do elemento cm (comentário).

Membro/Atributo Definição
authorId Refere-se à ID de um autor na lista de autores de comentários do documento.
Dt A data e a hora em que este comentário foi modificado pela última vez.
Idx Um identificador para este comentário que é exclusivo dentro de uma lista de todos os comentários deste autor neste documento. O primeiro comentário de um autor em um documento tem índice 1.
Pos As informações de posicionamento para o posicionamento de um comentário em uma superfície de slide.
texto Texto de comentário.
extLst Especifica a lista de extensão com capacidade de modificação na qual todas as extensões futuras do tipo de elemento são definidas. A lista de extensão junto com as extensões futuras correspondentes é usada para estender os recursos de armazenamento da estrutura PresentationML. Isso permite que vários novos tipos de dados sejam armazenados nativamente dentro da estrutura.

O exemplo de código de esquema XML a seguir define os membros do elemento cm , além dos atributos necessários e opcionais.

    <complexType name="CT_Comment">
       <sequence>
           <element name="pos" type="a:CT_Point2D" minOccurs="1" maxOccurs="1"/>
           <element name="text" type="xsd:string" minOccurs="1" maxOccurs="1"/>
           <element name="extLst" type="CT_ExtensionListModify" minOccurs="0" maxOccurs="1"/>
       </sequence>
       <attribute name="authorId" type="xsd:unsignedInt" use="required"/>
       <attribute name="dt" type="xsd:dateTime" use="optional"/>
       <attribute name="idx" type="ST_Index" use="required"/>
    </complexType>

Código de exemplo

O exemplo de código a seguir mostra como adicionar comentários a um documento de apresentação. Para executar o programa, você pode passar os argumentos:

dotnet run -- [filePath] [initials] [name] [test ...]

Observação

Para obter o nome e as iniciais exatos do autor, abra o arquivo de apresentação e clique no item menu Arquivo e clique em Opções. A janela PowerPointOptions é aberta e o conteúdo da guia Geral é exibido. O nome e as iniciais do autor devem corresponder ao nome de usuário e às iniciais nesta guia.

using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Presentation;
using System;
using System.Linq;

AddCommentToPresentation(args[0], args[1], args[2], string.Join(' ', args[3..]));

static void AddCommentToPresentation(string file, string initials, string name, string text)
{
    using (PresentationDocument doc = PresentationDocument.Open(file, true))
    {

        // Declare a CommentAuthorsPart object.
        CommentAuthorsPart authorsPart;

        // If the presentation does not contain a comment authors part, add a new one.
        PresentationPart presentationPart = doc.PresentationPart ?? doc.AddPresentationPart();

        // Verify that there is an existing comment authors part and add a new one if not.
        authorsPart = presentationPart.CommentAuthorsPart ?? presentationPart.AddNewPart<CommentAuthorsPart>();

        // Verify that there is a comment author list in the comment authors part and add one if not.
        CommentAuthorList authorList = authorsPart.CommentAuthorList ?? new CommentAuthorList();
        authorsPart.CommentAuthorList = authorList;

        // Declare a new author ID as either the max existing ID + 1 or 1 if there are no existing IDs.
        uint authorId = authorList.Elements<CommentAuthor>().Select(a => a.Id?.Value).Max() ?? 0;
        authorId++;
        // If there is an existing author with matching name and initials, use that author otherwise create a new CommentAuthor.
        var foo = authorList.Elements<CommentAuthor>().Where(a => a.Name == name && a.Initials == initials).FirstOrDefault();
        CommentAuthor author = foo ??
            authorList.AppendChild
                (new CommentAuthor()
                {
                    Id = authorId,
                    Name = name,
                    Initials = initials,
                    ColorIndex = 0
                });
        // get the author id
        authorId = author.Id ?? authorId;

        // Get the first slide, using the GetFirstSlide method.
        SlidePart slidePart1 = GetFirstSlide(doc);

        // Declare a comments part.
        SlideCommentsPart commentsPart;

        // Verify that there is a comments part in the first slide part.
        if (slidePart1.GetPartsOfType<SlideCommentsPart>().Count() == 0)
        {
            // If not, add a new comments part.
            commentsPart = slidePart1.AddNewPart<SlideCommentsPart>();
        }
        else
        {
            // Else, use the first comments part in the slide part.
            commentsPart = slidePart1.GetPartsOfType<SlideCommentsPart>().First();
        }

        // If the comment list does not exist.
        if (commentsPart.CommentList is null)
        {
            // Add a new comments list.
            commentsPart.CommentList = new CommentList();
        }

        // Get the new comment ID.
        uint commentIdx = author.LastIndex is null ? 1 : author.LastIndex + 1;
        author.LastIndex = commentIdx;

        // Add a new comment.
        Comment comment = commentsPart.CommentList.AppendChild<Comment>(
            new Comment()
            {
                AuthorId = authorId,
                Index = commentIdx,
                DateTime = DateTime.Now
            });

        // Add the position child node to the comment element.
        comment.Append(
            new Position() { X = 100, Y = 200 },
            new Text() { Text = text });

        // Save the comment authors part.
        authorList.Save();

        // Save the comments part.
        commentsPart.CommentList.Save();
    }
}

// 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;
    SlideId? slideId = part?.Presentation?.SlideIdList?.GetFirstChild<SlideId>();
    string? relId = slideId?.RelationshipId;
    if (relId is null)
    {
        throw new ArgumentNullException("The first slide does not contain a relationship ID.");
    }
    // Get the slide part by the relationship ID.
    SlidePart? slidePart = part?.GetPartById(relId) as SlidePart;

    if (slidePart is null)
    {
        throw new ArgumentNullException("The slide part is null.");
    }

    return slidePart;
}