Удалить слайд из презентации
В этом разделе показано, как программно удалить слайд из презентации с помощью пакета SDK Open XML для Office. Также здесь показано, как удалить все ссылки на слайд из любых презентаций, которые могут существовать. Для удаления определенного слайда из файла презентации необходимо прежде всего знать число слайдов в презентации. Поэтому в данном практическом руководстве код разделен на две части. В первой части определяется число слайдов, а во второй удаляется слайд с указанным индексом.
Примечание.
Для удаления слайда из более сложных презентаций, например из содержащих параметры режима структуры, могут потребоваться дополнительные действия.
Получение объекта Presentation
В пакете SDK Open PresentationDocument XML класс представляет пакет документов презентации. Чтобы работать с документом презентации, сначала создайте экземпляр PresentationDocument
класса , а затем работайте с этим экземпляром. Чтобы создать экземпляр класса из документа, вызовите одну из Open
перегрузок метода. В коде в этом разделе используется Open метод , который принимает путь к файлу в качестве первого параметра для указания открываемого файла, а логическое значение — в качестве второго параметра для указания возможности редактирования документа. Присвойте этому второму параметру значение false
, чтобы открыть файл только для чтения, или true
, если вы хотите открыть файл для доступа на чтение и запись. В этом разделе с помощью кода файл открывается дважды: один раз для определения числа слайдов, и еще один раз для удаления определенного слайда. При определении числа слайдов в презентации рекомендуется отрыть файл с доступом только для чтения, чтобы защитить его от случайной записи.
using
Следующая инструкция открывает файл для доступа только для чтения. В этом примере кода параметр представляет собой строку, presentationFile
представляющую путь к файлу, из которого требуется открыть документ.
// Open the presentation as read-only.
using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationFile, false))
Чтобы удалить слайд из файла презентации, откройте его для чтения и записи, как показано в следующей using
инструкции.
// Open the source document as read/write.
using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationFile, true))
В версии 3.0.0+ Close() метод был удален в пользу использования инструкции using.
Это гарантирует автоматический Dispose() вызов метода при достижении закрывающей фигурной скобки. Блок, следующий за using
оператором , устанавливает область для объекта, созданного или именованного в инструкцииusing
, в данном случае presentationDocument
.
Базовая структура документа презентации
Базовая структура PresentationML
документа состоит из нескольких частей, среди которых есть main часть, содержащая определение презентации. В следующем тексте из спецификации ISO/IEC 29500 представлена общая форма PresentationML
пакета.
Main часть
PresentationML
пакета начинается с корневого элемента презентации. Этот элемент содержит презентацию, которая, в свою очередь, ссылается на список слайдов, список образцов слайдов, список образцов заметок и список образцов раздаточных материалов. Список слайдов ссылается на все слайды в презентации; список образцов слайдов ссылается на все образцы слайдов, используемые в презентации; в списке образцов заметок содержатся данные о форматировании страниц заметок, а в списке образцов раздаточных материалов описан внешний вид раздаточных материалов.Раздаточные материалы представляют собой набор распечатанных слайдов, которые можно раздать слушателям для последующего использования.
Наряду с текстом и изображениями слайды могут содержать комментарии, заметки и разметку, а также могут входить в одну или несколько пользовательских презентаций. Комментарий представляет собой примечание, которое адресовано сотруднику, ответственному за обслуживание набора слайдов. Заметка представляет собой напоминание или отрывок текста, предназначенный для докладчика или для слушателей.
Другие функции документа
PresentationML
могут включать следующие: анимацию, звук, видео и переходы между слайдами.Документ
PresentationML
не хранится в виде одного большого текста в одной части. Элементы с определенной группировкой функций хранятся в различных частях. Например, все авторы в документе хранятся в одной части авторов, а каждый слайд имеет свою собственную часть.ISO/IEC 29500: 2016
Указанный ниже пример кода XML описывает презентацию, содержащую 2 слайда с идентификаторами 267 и 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>
С помощью пакета SDK Open XML можно создавать структуру документа и содержимое с помощью строго типизированных классов, соответствующих элементам PresentationML. Эти классы можно найти в пространстве имен. В следующей таблице перечислены имена классов, которые соответствуют sld
элементам , sldLayout
, sldMaster
и notesMaster
.
Элемент PresentationML | Класс пакета SDK Open XML | Описание |
---|---|---|
<sld/> |
Slide | Слайд презентации. Это корневой элемент части SlidePart. |
<sldLayout/> |
SlideLayout | Разметка слайда. Это корневой элемент части SlideLayoutPart. |
<sldMaster/> |
SlideMaster | Образец слайда. Это корневой элемент части SlideMasterPart. |
<notesMaster/> |
NotesMaster | Образец заметок (или handoutMaster). Это корневой элемент части NotesMasterPart. |
Подсчет количества слайдов
Пример кода состоит из двух перегрузок CountSlides
метода . Первая перегрузка использует параметр, string
а вторая перегрузка PresentationDocument
— параметр . В первом CountSlides
методе пример кода открывает документ презентации в инструкции using
. Затем объект передается PresentationDocument
во второй CountSlides
метод, который возвращает целочисленное число, представляющее количество слайдов в презентации.
// Pass the presentation to the next CountSlide method
// and return the slide count.
return CountSlides(presentationDocument);
Во втором CountSlides
методе код проверяет, что переданный PresentationDocument
объект не является , и если это не null
так, он получает PresentationPart
объект из PresentationDocument
объекта . С помощью SlideParts
кода получает slideCount и возвращает его.
if (presentationDocument is null)
{
throw new ArgumentNullException("presentationDocument");
}
int slidesCount = 0;
// Get the presentation part of document.
PresentationPart? presentationPart = presentationDocument.PresentationPart;
// Get the slide count from the SlideParts.
if (presentationPart is not null)
{
slidesCount = presentationPart.SlideParts.Count();
}
// Return the slide count to the previous method.
return slidesCount;
Удаление определенного слайда
Код для удаления слайда использует две перегрузки DeleteSlide
метода . Первый перегруженный DeleteSlide
метод принимает два параметра: строку, представляющую имя файла презентации и путь, и целое число, представляющее отсчитываемое от нуля положение индекса удаляемого слайда. Он открывает файл презентации для доступа на чтение и запись, получает PresentationDocument
объект, а затем передает этот объект и номер индекса в следующий перегруженный DeleteSlide
метод, который выполняет удаление.
// Get the presentation object and pass it to the next DeleteSlide method.
static void DeleteSlide(string presentationFile, int slideIndex)
{
// Open the source document as read/write.
using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationFile, true))
{
// Pass the source document and the index of the slide to be deleted to the next DeleteSlide method.
DeleteSlide(presentationDocument, slideIndex);
}
}
В первом разделе второго перегруженного DeleteSlide
метода используется CountSlides
метод для получения количества слайдов в презентации. Затем он получает список идентификаторов слайдов в презентации, находит указанный слайд в списке слайдов и удаляет его.
// Delete the specified slide from the presentation.
static void DeleteSlide(PresentationDocument presentationDocument, int slideIndex)
{
if (presentationDocument is null)
{
throw new ArgumentNullException(nameof(presentationDocument));
}
// Use the CountSlides sample to get the number of slides in the presentation.
int slidesCount = CountSlides(presentationDocument);
if (slideIndex < 0 || slideIndex >= slidesCount)
{
throw new ArgumentOutOfRangeException("slideIndex");
}
// Get the presentation part from the presentation document.
PresentationPart? presentationPart = presentationDocument.PresentationPart;
// Get the presentation from the presentation part.
Presentation? presentation = presentationPart?.Presentation;
// Get the list of slide IDs in the presentation.
SlideIdList? slideIdList = presentation?.SlideIdList;
// Get the slide ID of the specified slide
SlideId? slideId = slideIdList?.ChildElements[slideIndex] as SlideId;
// Get the relationship ID of the slide.
string? slideRelId = slideId?.RelationshipId;
// If there's no relationship ID, there's no slide to delete.
if (slideRelId is null)
{
return;
}
// Remove the slide from the slide list.
slideIdList!.RemoveChild(slideId);
В следующем разделе второго перегруженного DeleteSlide
метода удаляются все ссылки на удаленный слайд из пользовательских показов. Для этого выполняется итерация по списку пользовательских презентаций и по списку слайдов в каждой пользовательской презентации.
Затем объявляется связанный список записей списка слайдов и создается его экземпляр, после чего с помощью идентификатора связи удаленного слайда находятся ссылки на этот слайд. Эти ссылки добавляются в список записей слайдов, а затем каждая ссылка удаляется из списков слайдов соответствующих пользовательских презентаций.
// Remove references to the slide from all custom shows.
if (presentation!.CustomShowList is not null)
{
// Iterate through the list of custom shows.
foreach (var customShow in presentation.CustomShowList.Elements<CustomShow>())
{
if (customShow.SlideList is not null)
{
// Declare a link list of slide list entries.
LinkedList<SlideListEntry> slideListEntries = new LinkedList<SlideListEntry>();
foreach (SlideListEntry slideListEntry in customShow.SlideList.Elements())
{
// Find the slide reference to remove from the custom show.
if (slideListEntry.Id is not null && slideListEntry.Id == slideRelId)
{
slideListEntries.AddLast(slideListEntry);
}
}
// Remove all references to the slide from the custom show.
foreach (SlideListEntry slideListEntry in slideListEntries)
{
customShow.SlideList.RemoveChild(slideListEntry);
}
}
}
}
Наконец, код удаляет часть слайда для удаленного слайда.
// Get the slide part for the specified slide.
SlidePart slidePart = (SlidePart)presentationPart!.GetPartById(slideRelId);
// Remove the slide part.
presentationPart.DeletePart(slidePart);
Пример кода
Ниже приведен полный пример кода на языках C# и Visual Basic.
// Get the presentation object and pass it to the next CountSlides method.
static int CountSlides(string presentationFile)
{
// Open the presentation as read-only.
using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationFile, false))
{
// Pass the presentation to the next CountSlide method
// and return the slide count.
return CountSlides(presentationDocument);
}
}
// Count the slides in the presentation.
static int CountSlides(PresentationDocument presentationDocument)
{
if (presentationDocument is null)
{
throw new ArgumentNullException("presentationDocument");
}
int slidesCount = 0;
// Get the presentation part of document.
PresentationPart? presentationPart = presentationDocument.PresentationPart;
// Get the slide count from the SlideParts.
if (presentationPart is not null)
{
slidesCount = presentationPart.SlideParts.Count();
}
// Return the slide count to the previous method.
return slidesCount;
}
// Get the presentation object and pass it to the next DeleteSlide method.
static void DeleteSlide(string presentationFile, int slideIndex)
{
// Open the source document as read/write.
using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationFile, true))
{
// Pass the source document and the index of the slide to be deleted to the next DeleteSlide method.
DeleteSlide(presentationDocument, slideIndex);
}
}
// Delete the specified slide from the presentation.
static void DeleteSlide(PresentationDocument presentationDocument, int slideIndex)
{
if (presentationDocument is null)
{
throw new ArgumentNullException(nameof(presentationDocument));
}
// Use the CountSlides sample to get the number of slides in the presentation.
int slidesCount = CountSlides(presentationDocument);
if (slideIndex < 0 || slideIndex >= slidesCount)
{
throw new ArgumentOutOfRangeException("slideIndex");
}
// Get the presentation part from the presentation document.
PresentationPart? presentationPart = presentationDocument.PresentationPart;
// Get the presentation from the presentation part.
Presentation? presentation = presentationPart?.Presentation;
// Get the list of slide IDs in the presentation.
SlideIdList? slideIdList = presentation?.SlideIdList;
// Get the slide ID of the specified slide
SlideId? slideId = slideIdList?.ChildElements[slideIndex] as SlideId;
// Get the relationship ID of the slide.
string? slideRelId = slideId?.RelationshipId;
// If there's no relationship ID, there's no slide to delete.
if (slideRelId is null)
{
return;
}
// Remove the slide from the slide list.
slideIdList!.RemoveChild(slideId);
// Remove references to the slide from all custom shows.
if (presentation!.CustomShowList is not null)
{
// Iterate through the list of custom shows.
foreach (var customShow in presentation.CustomShowList.Elements<CustomShow>())
{
if (customShow.SlideList is not null)
{
// Declare a link list of slide list entries.
LinkedList<SlideListEntry> slideListEntries = new LinkedList<SlideListEntry>();
foreach (SlideListEntry slideListEntry in customShow.SlideList.Elements())
{
// Find the slide reference to remove from the custom show.
if (slideListEntry.Id is not null && slideListEntry.Id == slideRelId)
{
slideListEntries.AddLast(slideListEntry);
}
}
// Remove all references to the slide from the custom show.
foreach (SlideListEntry slideListEntry in slideListEntries)
{
customShow.SlideList.RemoveChild(slideListEntry);
}
}
}
}
// Get the slide part for the specified slide.
SlidePart slidePart = (SlidePart)presentationPart!.GetPartById(slideRelId);
// Remove the slide part.
presentationPart.DeletePart(slidePart);
}