プレゼンテーションに新しいスライドを挿入する
このトピックでは、Open XML SDK のクラスを使用して、プログラムを使用してプレゼンテーションに新しいスライドを挿入する方法について説明します。
PresentationDocument オブジェクトを取得する
Open XML SDK では、 PresentationDocument クラスはプレゼンテーション ドキュメント パッケージを表します。 プレゼンテーション ドキュメントを操作するには、まず PresentationDocument
クラスのインスタンスを作成してから、そのインスタンスを操作します。 ドキュメントからクラス インスタンスを作成するには、ファイル パスを使用する Open メソッドを呼び出し、2 番目のパラメーターとしてブール値を使用してドキュメントを編集可能にするかどうかを指定します。 読み取り/書き込みのためにドキュメントを開くには、次のusing
ステートメントに示すように、このパラメーターの値true
を指定します。
このコード セグメントでは、 presentationFile
パラメーターは、ドキュメントを開くファイルの完全なパスを表す文字列です。
// Open the source document as read/write.
using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationFile, true))
v3.0.0 以降では、using ステートメントに依存することを優先して、Close() メソッドが削除されました。
これにより、閉じかっこに達したときに、 Dispose() メソッドが自動的に呼び出されます。
using
ステートメントに続くブロックは、using
ステートメントで作成または名前付けされたオブジェクトのスコープを確立します(この場合はpresentationDocument
。
プレゼンテーション ドキュメントの基本構造
PresentationML
ドキュメントの基本的なドキュメント構造は、多数のパーツで構成され、その中にはプレゼンテーション定義を含むメインパーツがあります。
ISO/IEC 29500 仕様の次のテキストでは、PresentationML
パッケージの全体的な形式について説明します。
PresentationML
パッケージのメイン部分は、プレゼンテーション ルート要素で始まります。 この要素にはプレゼンテーションが含まれており、プレゼンテーションは スライド リスト、スライド マスター リスト、ノート マスター リスト、配布資料マスター リストを参照します。 スライド リストはプレゼンテーション内のすべてのスライドを参照します。スライド マスター リストはプレゼンテーションで使用されるスライド マスター全体を参照します。ノート マスターにはノート ページの書式設定に関する情報が含まれます。配布資料マスターは配布資料がどのように表示されるかを示します。配布資料とは、聴衆に提供できるように一連のスライドを印刷したものです。
テキストやグラフィックのように、各スライドにはコメントとノートを含めることができ、レイアウトを指定したり、1 つ以上のカスタム プレゼンテーションに組み込んだりできます。 コメントは、プレゼンテーション スライド デッキをメンテナンスする人向けの注釈です。 ノートは、プレゼンテーションの発表者または参加者向けのリマインダーやメモです。
PresentationML
ドキュメントには、アニメーション、オーディオ、ビデオ、スライド間の切り替えなどのその他の機能があります。
PresentationML
ドキュメントは、1 つのパーツに 1 つの大きな本文として格納されません。 その代わりに、特定のグループの機能を実現する要素が別個のパーツに格納されます。 たとえば、ドキュメント内のすべての作成者は 1 つの作成者パーツに格納され、各スライドには独自のパーツがあります。ISO/IEC 29500: 2016
次の 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 要素に対応する厳密に型指定されたクラスを使用して、ドキュメント構造とコンテンツを作成できます。 これらのクラスは、 名前空間にあります。 次の表に、 sld
、 sldLayout
、 sldMaster
、および notesMaster
の各要素に対応するクラスのクラス名を示します。
PresentationML 要素 | Open XML SDK クラス | 説明 |
---|---|---|
<sld/> |
Slide | プレゼンテーション スライド。 SlidePart のルート要素 |
<sldLayout/> |
SlideLayout | スライド レイアウト。 SlideLayoutPart のルート要素 |
<sldMaster/> |
SlideMaster | スライド マスター。 SlideMasterPart のルート要素 |
<notesMaster/> |
NotesMaster | ノート マスター (または handoutMaster)。 NotesMasterPart のルート要素 |
サンプル コードの動作のしくみ
サンプル コードは、 InsertNewSlide
メソッドの 2 つのオーバーロードで構成されます。 最初のオーバーロード メソッドへの 3 つのパラメーターとして、スライドを追加するプレゼンテーション ファイルの完全パス、0 から始まるスライドのインデックス位置 (プレゼンテーション内のスライドを追加する位置を示す) を表す整数、および新しいスライドのタイトルを表す文字列を渡します。 プレゼンテーション ファイルを読み取り/書き込みとして開き、 PresentationDocument
オブジェクトを取得し、そのオブジェクトを 2 つ目のオーバーロードされた InsertNewSlide
メソッドに渡します。このメソッドは、挿入を実行します。
// Insert a slide into the specified presentation.
public static void InsertNewSlide(string presentationFile, int position, string slideTitle)
{
// Open the source document as read/write.
using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationFile, true))
{
// Pass the source document and the position and title of the slide to be inserted to the next method.
InsertNewSlide(presentationDocument, position, slideTitle);
}
}
2 つ目のオーバーロードされた InsertNewSlide
メソッドは、新しい Slide
オブジェクトを作成し、そのプロパティを設定してから、プレゼンテーションのスライド順序に挿入します。 このメソッドの最初のセクションでは、スライドを作成し、そのプロパティを設定します。
// Insert the specified slide into the presentation at the specified position.
public static SlidePart InsertNewSlide(PresentationDocument presentationDocument, int position, string slideTitle)
{
PresentationPart? presentationPart = presentationDocument.PresentationPart;
// Verify that the presentation is not empty.
if (presentationPart is null)
{
throw new InvalidOperationException("The presentation document is empty.");
}
// Declare and instantiate a new slide.
Slide slide = new Slide(new CommonSlideData(new ShapeTree()));
uint drawingObjectId = 1;
// Construct the slide content.
// Specify the non-visual properties of the new slide.
CommonSlideData commonSlideData = slide.CommonSlideData ?? slide.AppendChild(new CommonSlideData());
ShapeTree shapeTree = commonSlideData.ShapeTree ?? commonSlideData.AppendChild(new ShapeTree());
NonVisualGroupShapeProperties nonVisualProperties = shapeTree.AppendChild(new NonVisualGroupShapeProperties());
nonVisualProperties.NonVisualDrawingProperties = new NonVisualDrawingProperties() { Id = 1, Name = "" };
nonVisualProperties.NonVisualGroupShapeDrawingProperties = new NonVisualGroupShapeDrawingProperties();
nonVisualProperties.ApplicationNonVisualDrawingProperties = new ApplicationNonVisualDrawingProperties();
// Specify the group shape properties of the new slide.
shapeTree.AppendChild(new GroupShapeProperties());
2 つ目のオーバーロードされた InsertNewSlide
メソッドの次のセクションでは、スライドにタイトル図形を追加し、テキストを含むプロパティを設定します。
// Declare and instantiate the title shape of the new slide.
Shape titleShape = shapeTree.AppendChild(new Shape());
drawingObjectId++;
// Specify the required shape properties for the title shape.
titleShape.NonVisualShapeProperties = new NonVisualShapeProperties
(new NonVisualDrawingProperties() { Id = drawingObjectId, Name = "Title" },
new NonVisualShapeDrawingProperties(new Drawing.ShapeLocks() { NoGrouping = true }),
new ApplicationNonVisualDrawingProperties(new PlaceholderShape() { Type = PlaceholderValues.Title }));
titleShape.ShapeProperties = new ShapeProperties();
// Specify the text of the title shape.
titleShape.TextBody = new TextBody(new Drawing.BodyProperties(),
new Drawing.ListStyle(),
new Drawing.Paragraph(new Drawing.Run(new Drawing.Text() { Text = slideTitle })));
2 つ目のオーバーロードされた InsertNewSlide
メソッドの次のセクションでは、スライドに本文の図形を追加し、テキストを含むプロパティを設定します。
// Declare and instantiate the body shape of the new slide.
Shape bodyShape = shapeTree.AppendChild(new Shape());
drawingObjectId++;
// Specify the required shape properties for the body shape.
bodyShape.NonVisualShapeProperties = new NonVisualShapeProperties(new NonVisualDrawingProperties() { Id = drawingObjectId, Name = "Content Placeholder" },
new NonVisualShapeDrawingProperties(new Drawing.ShapeLocks() { NoGrouping = true }),
new ApplicationNonVisualDrawingProperties(new PlaceholderShape() { Index = 1 }));
bodyShape.ShapeProperties = new ShapeProperties();
// Specify the text of the body shape.
bodyShape.TextBody = new TextBody(new Drawing.BodyProperties(),
new Drawing.ListStyle(),
new Drawing.Paragraph());
2 つ目のオーバーロードされた InsertNewSlide
メソッドの最後のセクションでは、新しいスライド パーツを作成し、スライドを挿入する位置を指定したインデックス位置を見つけて挿入し、新しいスライドを新しいスライド パーツに割り当てます。
// Create the slide part for the new slide.
SlidePart slidePart = presentationPart.AddNewPart<SlidePart>();
// Assign the new slide to the new slide part
slidePart.Slide = slide;
// Modify the slide ID list in the presentation part.
// The slide ID list should not be null.
SlideIdList? slideIdList = presentationPart.Presentation.SlideIdList;
// Find the highest slide ID in the current list.
uint maxSlideId = 1;
SlideId? prevSlideId = null;
OpenXmlElementList slideIds = slideIdList?.ChildElements ?? default;
foreach (SlideId slideId in slideIds)
{
if (slideId.Id is not null && slideId.Id > maxSlideId)
{
maxSlideId = slideId.Id;
}
position--;
if (position == 0)
{
prevSlideId = slideId;
}
}
maxSlideId++;
// Get the ID of the previous slide.
SlidePart lastSlidePart;
if (prevSlideId is not null && prevSlideId.RelationshipId is not null)
{
lastSlidePart = (SlidePart)presentationPart.GetPartById(prevSlideId.RelationshipId!);
}
else
{
string? firstRelId = ((SlideId)slideIds[0]).RelationshipId;
// If the first slide does not contain a relationship ID, throw an exception.
if (firstRelId is null)
{
throw new ArgumentNullException(nameof(firstRelId));
}
lastSlidePart = (SlidePart)presentationPart.GetPartById(firstRelId);
}
// Use the same slide layout as that of the previous slide.
if (lastSlidePart.SlideLayoutPart is not null)
{
slidePart.AddPart(lastSlidePart.SlideLayoutPart);
}
// Insert the new slide into the slide list after the previous slide.
SlideId newSlideId = slideIdList!.InsertAfter(new SlideId(), prevSlideId);
newSlideId.Id = maxSlideId;
newSlideId.RelationshipId = presentationPart.GetIdOfPart(slidePart);
サンプル コード
以下に、C# と Visual Basic による完全なサンプル コードを示します。
// Insert a slide into the specified presentation.
public static void InsertNewSlide(string presentationFile, int position, string slideTitle)
{
// Open the source document as read/write.
using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationFile, true))
{
// Pass the source document and the position and title of the slide to be inserted to the next method.
InsertNewSlide(presentationDocument, position, slideTitle);
}
}
// Insert the specified slide into the presentation at the specified position.
public static SlidePart InsertNewSlide(PresentationDocument presentationDocument, int position, string slideTitle)
{
PresentationPart? presentationPart = presentationDocument.PresentationPart;
// Verify that the presentation is not empty.
if (presentationPart is null)
{
throw new InvalidOperationException("The presentation document is empty.");
}
// Declare and instantiate a new slide.
Slide slide = new Slide(new CommonSlideData(new ShapeTree()));
uint drawingObjectId = 1;
// Construct the slide content.
// Specify the non-visual properties of the new slide.
CommonSlideData commonSlideData = slide.CommonSlideData ?? slide.AppendChild(new CommonSlideData());
ShapeTree shapeTree = commonSlideData.ShapeTree ?? commonSlideData.AppendChild(new ShapeTree());
NonVisualGroupShapeProperties nonVisualProperties = shapeTree.AppendChild(new NonVisualGroupShapeProperties());
nonVisualProperties.NonVisualDrawingProperties = new NonVisualDrawingProperties() { Id = 1, Name = "" };
nonVisualProperties.NonVisualGroupShapeDrawingProperties = new NonVisualGroupShapeDrawingProperties();
nonVisualProperties.ApplicationNonVisualDrawingProperties = new ApplicationNonVisualDrawingProperties();
// Specify the group shape properties of the new slide.
shapeTree.AppendChild(new GroupShapeProperties());
// Declare and instantiate the title shape of the new slide.
Shape titleShape = shapeTree.AppendChild(new Shape());
drawingObjectId++;
// Specify the required shape properties for the title shape.
titleShape.NonVisualShapeProperties = new NonVisualShapeProperties
(new NonVisualDrawingProperties() { Id = drawingObjectId, Name = "Title" },
new NonVisualShapeDrawingProperties(new Drawing.ShapeLocks() { NoGrouping = true }),
new ApplicationNonVisualDrawingProperties(new PlaceholderShape() { Type = PlaceholderValues.Title }));
titleShape.ShapeProperties = new ShapeProperties();
// Specify the text of the title shape.
titleShape.TextBody = new TextBody(new Drawing.BodyProperties(),
new Drawing.ListStyle(),
new Drawing.Paragraph(new Drawing.Run(new Drawing.Text() { Text = slideTitle })));
// Declare and instantiate the body shape of the new slide.
Shape bodyShape = shapeTree.AppendChild(new Shape());
drawingObjectId++;
// Specify the required shape properties for the body shape.
bodyShape.NonVisualShapeProperties = new NonVisualShapeProperties(new NonVisualDrawingProperties() { Id = drawingObjectId, Name = "Content Placeholder" },
new NonVisualShapeDrawingProperties(new Drawing.ShapeLocks() { NoGrouping = true }),
new ApplicationNonVisualDrawingProperties(new PlaceholderShape() { Index = 1 }));
bodyShape.ShapeProperties = new ShapeProperties();
// Specify the text of the body shape.
bodyShape.TextBody = new TextBody(new Drawing.BodyProperties(),
new Drawing.ListStyle(),
new Drawing.Paragraph());
// Create the slide part for the new slide.
SlidePart slidePart = presentationPart.AddNewPart<SlidePart>();
// Assign the new slide to the new slide part
slidePart.Slide = slide;
// Modify the slide ID list in the presentation part.
// The slide ID list should not be null.
SlideIdList? slideIdList = presentationPart.Presentation.SlideIdList;
// Find the highest slide ID in the current list.
uint maxSlideId = 1;
SlideId? prevSlideId = null;
OpenXmlElementList slideIds = slideIdList?.ChildElements ?? default;
foreach (SlideId slideId in slideIds)
{
if (slideId.Id is not null && slideId.Id > maxSlideId)
{
maxSlideId = slideId.Id;
}
position--;
if (position == 0)
{
prevSlideId = slideId;
}
}
maxSlideId++;
// Get the ID of the previous slide.
SlidePart lastSlidePart;
if (prevSlideId is not null && prevSlideId.RelationshipId is not null)
{
lastSlidePart = (SlidePart)presentationPart.GetPartById(prevSlideId.RelationshipId!);
}
else
{
string? firstRelId = ((SlideId)slideIds[0]).RelationshipId;
// If the first slide does not contain a relationship ID, throw an exception.
if (firstRelId is null)
{
throw new ArgumentNullException(nameof(firstRelId));
}
lastSlidePart = (SlidePart)presentationPart.GetPartById(firstRelId);
}
// Use the same slide layout as that of the previous slide.
if (lastSlidePart.SlideLayoutPart is not null)
{
slidePart.AddPart(lastSlidePart.SlideLayoutPart);
}
// Insert the new slide into the slide list after the previous slide.
SlideId newSlideId = slideIdList!.InsertAfter(new SlideId(), prevSlideId);
newSlideId.Id = maxSlideId;
newSlideId.RelationshipId = presentationPart.GetIdOfPart(slidePart);
return slidePart;
}