Abrir documento de uma apresentação para acesso somente leitura
Este tópico descreve como utilizar as classes no SDK Open XML para o Office para abrir programaticamente um documento de apresentação para acesso só de leitura.
Como Abrir um Ficheiro para Read-Only Access
Poderá querer abrir um documento de apresentação para ler os diapositivos. Poderá querer extrair informações de um diapositivo, copiar um diapositivo para uma biblioteca de diapositivos ou listar os títulos dos diapositivos. Nesses casos, quer fazê-lo de uma forma que garanta que o documento permanece inalterado. Pode fazê-lo ao abrir o documento para acesso só de leitura. Este tópico How-To aborda várias formas de abrir programaticamente um documento de apresentação só de leitura.
Criar uma Instância da Classe PresentationDocument
No SDK Open XML, a PresentationDocument classe representa um pacote de documento de apresentação. Para trabalhar com um documento de apresentação, crie primeiro uma instância da PresentationDocument
classe e, em seguida, trabalhe com essa instância. Para criar a instância de classe a partir do documento, chame um dos Open métodos. São fornecidos vários métodos Open, cada um com uma assinatura diferente. A tabela seguinte contém um subconjunto das sobrecargas do Open
método que pode utilizar para abrir o pacote.
Nome | Descrição |
---|---|
Open | Crie uma nova instância da classe a PresentationDocument partir do ficheiro especificado. |
Open | Crie uma nova instância da classe a PresentationDocument partir do fluxo de E/S. |
Open | Crie uma nova instância da classe a PresentationDocument partir do pacote especificado. |
A tabela anterior inclui dois Open
métodos que aceitam um valor Booleano como segundo parâmetro para especificar se um documento é editável. Para abrir um documento para acesso só de leitura, especifique o valor false
para este parâmetro.
Por exemplo, pode abrir o ficheiro de apresentação como só de leitura e atribuí-lo a um PresentationDocument objeto, conforme mostrado na seguinte using
instrução. Neste código, o presentationFile
parâmetro é uma cadeia que representa o caminho do ficheiro a partir do qual pretende abrir o documento.
using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationFilePath, false))
{
// Insert other code here.
}
Também pode utilizar a segunda sobrecarga do Open
método, na tabela acima, para criar uma instância da PresentationDocument
classe com base num fluxo de E/S. Poderá utilizar esta abordagem se tiver uma aplicação Microsoft SharePoint Foundation 2010 que utilize E/S de fluxo e quiser utilizar o SDK Open XML para trabalhar com um documento. O segmento de código seguinte abre um documento com base num fluxo.
Stream stream = File.Open(strDoc, FileMode.Open);
using (PresentationDocument presentationDocument = PresentationDocument.Open(stream, false))
{
// Place other code here.
}
Suponha que tem uma aplicação que utiliza o suporte Open XML no System.IO.Packaging
espaço de nomes da Biblioteca de Classes .NET Framework e que pretende utilizar o SDK Open XML para trabalhar com um pacote só de leitura. O SDK Open XML inclui uma sobrecarga de método que aceita um Package
como único parâmetro. Não existe nenhum parâmetro Booleano para indicar se o documento deve ser aberto para edição. A abordagem recomendada é abrir o pacote como só de leitura antes de criar a instância da PresentationDocument
classe. O segmento de código seguinte executa esta operação.
Package presentationPackage = Package.Open(filepath, FileMode.Open, FileAccess.Read);
using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationPackage))
{
// Other code goes here.
}
Estrutura básica do documento de apresentação
A estrutura de documentos básica de um PresentationML
documento consiste em várias partes, entre as quais a main parte que contém a definição da apresentação. O texto seguinte da especificação ISO/IEC 29500 apresenta a forma geral de um PresentationML
pacote.
O main parte de um
PresentationML
pacote 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 diapositivos, a uma lista de master de diapositivos, a uma lista de notas master e a um folheto master lista. A lista de diapositivos refere-se a todos os diapositivos na apresentação; A lista de master de diapositivos refere-se a todos os modelos globais de diapositivos utilizados na apresentação; as notas master contêm informações sobre a formatação das páginas de notas; e o master de folheto descreve o aspeto de um folheto.Um folheto é um conjunto impresso de diapositivos que podem ser fornecidos a uma audiência.
Além de texto e gráficos, cada diapositivo pode conter comentários e notas, pode ter um esquema e pode fazer parte de uma ou mais apresentações personalizadas. Um comentário é uma anotação destinada à pessoa que mantém o conjunto de diapositivos da apresentação. Uma nota é um lembrete ou texto destinado ao apresentador ou à audiência.
Outras funcionalidades que um
PresentationML
documento pode incluir: animação, áudio, vídeo e transições entre diapositivos.Um
PresentationML
documento não é armazenado como um corpo grande numa única parte. Em vez disso, os elementos que implementam determinados agrupamentos de funcionalidades são armazenados em partes separadas. Por exemplo, todos os autores num documento são armazenados numa parte dos autores, enquanto cada diapositivo tem a sua própria parte.ISO/IEC 29500: 2016
O seguinte exemplo de código XML representa uma apresentação que contém dois diapositivos indicados pelos 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>
Com o SDK Open XML, pode criar a estrutura e o conteúdo do documento com classes com tipos fortes que correspondem a elementos PresentationML. Pode encontrar estas classes no espaço de nomes. A tabela seguinte lista os nomes das classes que correspondem aos sld
elementos , sldLayout
, sldMaster
e notesMaster
.
Elemento PresentationML | Abrir Classe SDK XML | Descrição |
---|---|---|
<sld/> |
Slide | Diapositivo de Apresentação. É o elemento raiz de SlidePart. |
<sldLayout/> |
SlideLayout | Esquema de Diapositivo. É o elemento raiz de SlideLayoutPart. |
<sldMaster/> |
SlideMaster | Modelo Global de Diapositivos. É o elemento raiz de SlideMasterPart. |
<notesMaster/> |
NotesMaster | Modelo Global de Notas (ou handoutMaster). É o elemento raiz de NotesMasterPart. |
Como funciona o código de exemplo
No código de exemplo, depois de abrir o documento de apresentação na using
instrução para acesso só de leitura, instanciar o PresentationPart
e abrir a lista de diapositivos. Em seguida, obtém o ID da relação do primeiro diapositivo.
// Get the relationship ID of the first slide.
PresentationPart? part = ppt.PresentationPart;
OpenXmlElementList slideIds = part?.Presentation?.SlideIdList?.ChildElements ?? default;
// If there are no slide IDs then there are no slides.
if (slideIds.Count == 0)
{
sldText = "";
return;
}
string? relId = (slideIds[index] as SlideId)?.RelationshipId;
if (relId is null)
{
sldText = "";
return;
}
No ID da relação, relId
, obtém a parte do diapositivo e, em seguida, o texto interno do diapositivo ao criar uma cadeia de texto com StringBuilder
.
// Get the slide part from the relationship ID.
SlidePart slide = (SlidePart)part!.GetPartById(relId);
// Build a StringBuilder object.
StringBuilder paragraphText = new StringBuilder();
// Get the inner text of the slide:
IEnumerable<A.Text> texts = slide.Slide.Descendants<A.Text>();
foreach (A.Text text in texts)
{
paragraphText.Append(text.Text);
}
sldText = paragraphText.ToString();
O texto interno do diapositivo, que é um out
parâmetro do GetSlideIdAndText
método, é transmitido de volta para o método main a apresentar.
Importante
Este exemplo apresenta apenas o texto no ficheiro de apresentação. Não são apresentadas partes que não sejam de texto, como formas ou gráficos.
Código de exemplo
O exemplo seguinte abre um ficheiro de apresentação para acesso só de leitura e obtém o texto interno de um diapositivo num índice especificado. Para chamar o método GetSlideIdAndText
pass no caminho completo do documento de apresentação. Transmita também o out
parâmetro sldText
, ao qual será atribuído um valor no próprio método e, em seguida, pode apresentar o respetivo valor no programa main. Por exemplo, a chamada seguinte para o GetSlideIdAndText
método obtém o texto interno num ficheiro de apresentação do índice e o caminho do ficheiro transmitidos para a aplicação como argumentos.
Dica
A exceção mais esperada neste programa é a ArgumentOutOfRangeException
exceção. Pode ser emitido se, por exemplo, tiver um ficheiro com dois diapositivos e quiser apresentar o texto no diapositivo número 4. Por conseguinte, é melhor utilizar um try
bloco quando chamar o GetSlideIdAndText
método, conforme mostrado no exemplo seguinte.
try
{
string file = args[0];
bool isInt = int.TryParse(args[1], out int i);
if (isInt)
{
GetSlideIdAndText(out string sldText, file, i);
Console.WriteLine($"The text in slide #{i + 1} is {sldText}");
}
}
catch(ArgumentOutOfRangeException exp) {
Console.Error.WriteLine(exp.Message);
}
Segue-se a listagem de código completa em C# e Visual Basic.
static void GetSlideIdAndText(out string sldText, string docName, int index)
{
using (PresentationDocument ppt = PresentationDocument.Open(docName, false))
{
// Get the relationship ID of the first slide.
PresentationPart? part = ppt.PresentationPart;
OpenXmlElementList slideIds = part?.Presentation?.SlideIdList?.ChildElements ?? default;
// If there are no slide IDs then there are no slides.
if (slideIds.Count == 0)
{
sldText = "";
return;
}
string? relId = (slideIds[index] as SlideId)?.RelationshipId;
if (relId is null)
{
sldText = "";
return;
}
// Get the slide part from the relationship ID.
SlidePart slide = (SlidePart)part!.GetPartById(relId);
// Build a StringBuilder object.
StringBuilder paragraphText = new StringBuilder();
// Get the inner text of the slide:
IEnumerable<A.Text> texts = slide.Slide.Descendants<A.Text>();
foreach (A.Text text in texts)
{
paragraphText.Append(text.Text);
}
sldText = paragraphText.ToString();
}
}