プレゼンテーションからスライドを削除する
このトピックでは、Open XML SDK for Office を使用してプレゼンテーションからスライドをプログラムで削除する方法について説明します。 また、存在する可能性があるカスタム ショーからスライドへのすべての参照を削除する方法も示します。 プレゼンテーション ファイル内の特定のスライドを削除するには、プレゼンテーション内のスライドの数を最初に把握しておく必要があります。 そのため、このハウツーのコードは 2 つの部分に分かれています。 1 つ目はスライドの数をカウントし、2 つ目は特定のインデックスでスライドを削除しています。
注:
[!メモ] アウトライン表示の設定を含むプレゼンテーションなど、より複雑なプレゼンテーションからスライドを削除する場合は、追加の手順が必要になることがあります。
Presentation オブジェクトの取得
Open XML SDK では、PresentationDocument クラスがプレゼンテーション ドキュメント パッケージを表します。 プレゼンテーション ドキュメントを操作するには、最初に PresentationDocument クラスのインスタンスを作成し、次にそのインスタンスを操作します。 ドキュメントからクラス インスタンスを作成するには、Open メソッド オーバーロードのいずれかを呼び出します。 このトピックのコードでは 、PresentationDocument.Open(String, Boolean) メソッドを使用します。このメソッドは、開くファイルを指定する最初のパラメーターとしてファイル パスを受け取り、ブール値を 2 番目のパラメーターとして使用して、ドキュメントが編集可能かどうかを指定します。 ファイルを読み取り専用アクセスで開くには、この 2 つ目のパラメーターを false に設定します。ファイルを読み取り/書き込みアクセスで開くには、true に設定します。 このトピックのコードはファイルを 2 回開きます。1 回目はスライドの数をカウントし、もう 1 回は特定のスライドを削除します。 プレゼンテーション内のスライドの数をカウントする場合、誤って書き込みをしてしまわないようにファイルを保護するため、読み取り専用アクセスでファイルを開くのが最善です。 次の using ステートメントにより、読み取り専用アクセスでファイルを開きます。 このコード例では、presentationFile パラメーターの文字列はドキュメントを開く元のファイルへのパスを表します。
// Open the presentation as read-only.
using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationFile, false))
{
// Insert other code here.
}
プレゼンテーション ファイルからスライドを削除するには、次の using ステートメントに示すように、ファイルを読み取り/書き込みアクセス用に開きます。
// Open the source document as read/write.
using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationFile, true))
{
// Place other code here.
}
The using statement provides a recommended alternative to the typical .Open, .Save, .Close sequence. これによって、閉じかっこに達したときに、 Dispose メソッド (Open XML SDK がリソースをクリーンアップするために使用する内部メソッド) が自動的に呼び出されます。 using ステートメントに続くブロックは、作成された、または using ステートメントで指定されたオブジェクト (この場合は presentationDocument) のスコープを設定します。
プレゼンテーション ドキュメントの基本構造
PresentationML ドキュメントの基本構造は、いくつかのパーツで構成され、そのうちの 1 つであるメイン パーツにプレゼンテーション定義が含まれます。 ISO/IEC 29500 仕様書では、PresentationML パッケージの全体的なフォームについて次のように説明しています。
PresentationML パッケージのメイン パーツは、プレゼンテーションのルート要素から始まります。 この要素にはプレゼンテーションが含まれており、プレゼンテーションは スライド リスト、スライド マスター リスト、ノート マスター リスト、配布資料マスター リストを参照します。 スライド リストはプレゼンテーション内のすべてのスライドを参照します。スライド マスター リストはプレゼンテーションで使用されるスライド マスター全体を参照します。ノート マスターにはノート ページの書式設定に関する情報が含まれます。配布資料マスターは配布資料がどのように表示されるかを示します。
配布資料とは、聴衆に提供できるように一連のスライドを印刷したものです。
テキストやグラフィックのように、各スライドにはコメントとノートを含めることができ、レイアウトを指定したり、1 つ以上のカスタム プレゼンテーションに組み込んだりできます。 コメントは、プレゼンテーション スライド デッキをメンテナンスする人向けの注釈です。 ノートは、発表者または聴衆向けのリマインダーまたはテキストの一部です。
PresentationML ドキュメントに含めることができるその他の機能には、アニメーション、オーディオ、ビデオ、スライド間の画面切り替え効果があります。
PresentationML ドキュメントは、1 つの大きな本体として単一のパーツに格納されるのではありません。 特定の機能を実装する要素ごとに、専用のパーツに格納されます。 たとえば、ドキュメント内のコメントはすべて 1 つのコメント パーツに格納され、各スライドは、スライド パーツに格納されます。
© ISO/IEC29500: 2008.
次の XML コードの例は、267 と 256 という ID で示される 2 つのスライドを含むプレゼンテーションを表します。
<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>
Open XML SDK を使用すると、PresentationML 要素に対応する厳密に型指定されたクラスを使用して、ドキュメント構造とコンテンツを作成できます。 これらのクラスは DocumentFormat.OpenXml.Presentation 名前空間にあります。 次の表に、sld、sldLayout、sldMaster、notesMaster の各要素に対応するクラスのクラス名を示します。
PresentationML の要素 | Open XML SDK クラス | 説明 |
---|---|---|
sld | Slide | プレゼンテーション スライド。 SlidePart のルート要素 |
sldLayout | SlideLayout | スライド レイアウト。 SlideLayoutPart のルート要素 |
sldMaster | SlideMaster | スライド マスター。 SlideMasterPart のルート要素 |
notesMaster | NotesMaster | ノート マスター (または handoutMaster)。 NotesMasterPart のルート要素 |
スライドの数をカウントする
サンプル コードは 、CountSlides メソッドの 2 つのオーバーロードで構成されます。 最初のオーバーロードは 文字列 パラメーターを使用し、2 番目のオーバーロードでは PresentationDocument パラメーターを使用します。 1 つ目の CountSlides メソッドでは、プレゼンテーション ドキュメントを using ステートメントで開きます。 PresentationDocument オブジェクトを 2 つ目の CountSlides メソッドに渡すと、プレゼンテーション内のスライド数を表す整数が返されます。
// Pass the presentation to the next CountSlides method
// and return the slide count.
return CountSlides(presentationDocument);
2 つ目の CountSlides メソッドで、このコードは渡された PresentationDocument オブジェクトが null ではないことを確認し、null ではない場合は、 PresentationDocument オブジェクトから PresentationPart オブジェクトを取得します。 コードでは、 SlideParts を使用して、slideCount を取得してこれを返しています。
// Check for a null document object.
if (presentationDocument == 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 != null)
{
slidesCount = presentationPart.SlideParts.Count();
}
// Return the slide count to the previous method.
return slidesCount;
特定のスライドを削除する
スライドを削除するためのコードでは、 DeleteSlide メソッドの 2 つのオーバーロードが使用されます。 最初にオーバーロードされた DeleteSlide メソッドは、プレゼンテーション ファイル名とパスを表す文字列と、削除するスライドの 0 から始まるインデックス位置を表す整数の 2 つのパラメーターを受け取ります。 読み取り/書き込みアクセス用のプレゼンテーション ファイルを開き、 PresentationDocument オブジェクトを取得し、そのオブジェクトとインデックス番号を、削除を実行する次のオーバーロードされた DeleteSlide メソッドに渡します。
// Get the presentation object and pass it to the next DeleteSlide method.
public 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);
}
}
2 つ目のオーバーロードされた DeleteSlide メソッドの 1 番目のセクションでは、 CountSlides メソッドを使用して、プレゼンテーション内にあるスライドの数を取得します。 次に、プレゼンテーションにあるスライド ID のリストを取得し、指定したスライドをスライド リストの中で探して、そのスライドをスライド リストから削除します。
// Delete the specified slide from the presentation.
public static void DeleteSlide(PresentationDocument presentationDocument, int slideIndex)
{
if (presentationDocument == null)
{
throw new ArgumentNullException("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;
// Remove the slide from the slide list.
slideIdList.RemoveChild(slideId);
2 つ目のオーバーロードされた DeleteSlide メソッドの次のセクションでは、削除されたスライドへのすべての参照をユーザー設定のスライド ショーから削除します。 この作業は、ユーザー設定のスライド ショーのリストと、それらの各スライド ショーにあるスライドのリストの反復処理によって行われます。 続いてこのメソッドは、スライド リスト エントリのリンクされたリストを宣言およびインスタンス化し、削除されたスライドのリレーションシップ ID を使用してそのスライドへの参照を見つけ出します。 さらに、それらの参照をスライド リスト エントリのリストに追加した後、各参照をそれぞれのユーザー設定のスライド ショーのスライド リストから削除します。
// Remove references to the slide from all custom shows.
if (presentation.CustomShowList != null)
{
// Iterate through the list of custom shows.
foreach (var customShow in presentation.CustomShowList.Elements<CustomShow>())
{
if (customShow.SlideList != 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 != 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);
}
}
}
}
コードの最後では、変更されたプレゼンテーションを保存し、削除されたスライドのスライド パーツを削除します。
// Save the modified presentation.
presentation.Save();
// Get the slide part for the specified slide.
SlidePart slidePart = presentationPart.GetPartById(slideRelId) as SlidePart;
// Remove the slide part.
presentationPart.DeletePart(slidePart);
}
サンプル コード
オーバーロードされた 2 つのメソッド CountSlides と DeleteSlide の完全なサンプル コードを次に示します。 コードを使用するには、次の呼び出しを例として使用して、プレゼンテーション ファイル "Myppt6.pptx" のインデックス 2 にあるスライドを削除できます。
DeleteSlide(@"C:\Users\Public\Documents\Myppt6.pptx", 2);
また、プレゼンテーション内のスライド数をカウントするには、次の呼び出しを使用できます。
Console.WriteLine("Number of slides = {0}",
CountSlides(@"C:\Users\Public\Documents\Myppt6.pptx"));
削除を実行する前後でスライド数をカウントすることをお勧めします。
以下は、C# および Visual Basic の完全なサンプル コードです。
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Presentation;
using System;
using System.Collections.Generic;
using System.Linq;
CountSlides(args[0]);
// 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 CountSlidesFromPresentation(presentationDocument);
}
}
// Count the slides in the presentation.
static int CountSlidesFromPresentation(PresentationDocument presentationDocument)
{
int slidesCount = 0;
// Get the presentation part of document.
PresentationPart presentationPart = presentationDocument.PresentationPart ?? presentationDocument.AddPresentationPart();
// 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.
DeleteSlideFromPresentation(presentationDocument, slideIndex);
}
}
// Delete the specified slide from the presentation.
static void DeleteSlideFromPresentation(PresentationDocument presentationDocument, int slideIndex)
{
if (presentationDocument is null)
{
throw new ArgumentNullException("presentationDocument");
}
// Use the CountSlides sample to get the number of slides in the presentation.
int slidesCount = CountSlidesFromPresentation(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);
}
}
}
}
// Save the modified presentation.
presentation.Save();
// Get the slide part for the specified slide.
SlidePart slidePart = (SlidePart)presentationPart!.GetPartById(slideRelId);
// Remove the slide part.
presentationPart.DeletePart(slidePart);
}