C#でOpenXML SDKを使ってPowerPointファイル(*.pptx)の出力を行う


はじめに

この記事はC#でMarkdownをパースしてオリジナルの出力を行う(markdigを使用)の続編です。

上記記事の中で書いたMarkdownを PPTXにするツールはOpenXML SDKを使用してPPTXファイルを作成しています。 このOpenXML SDKの使い方が最初すごい苦労したのでその部分について今回の記事は書くことにしました。

なお作成したMarkdownをPPTXに変換するツールはGithubにあげてあります。

OpenXMLとは

Office2007から使われだしたファイルフォーマットでXMLファイルをzipで固めたものです。 そのためファイルの拡張子を.zipに変更してから解凍すると、中に入っているXMLファイルを見ることができます。 以前のバイナリ形式とは違いOfficeがインストールされていない環境でも作成することができます。

作成する環境

以下の感じです

OpenXML SDKについて

OpenXMLの記載方法は以下の公式サイトを参考にしました https://docs.microsoft.com/en-us/office/open-xml/open-xml-sdk

ただ上記サイトの説明のみでは理解するのにかなり時間がかかると思われるので、もしこれからOpenXML SDKを使うかたには以下の方法をお勧めします。

Open XML SDK Productivity Tool

https://www.microsoft.com/en-us/download/details.aspx?id=30425

このツールを使用すると、指定したOpenXML形式のファイル(xlsxとかpptx)の中身の構造を確認することができます。 またツールを作るのに役立つのが、画面右側の領域に読み込んだファイルを作成するのに必要なC#のコードが出る機能です。

なので、自分の実装したい内容のファイルを作成し読み込んでC#のコードを確認していくと、100%理解しなくても動くものができる可能性がグッと近くなります。

私はこれを使ってちょっとずつ差分を見ながら欲しいコードを見つけてました。

例)フォントの太字をどうすればよいかを知りたいとき

PowerPointのOpenXMLクラス構成 解説

基本的に上記に説明したOpen XML SDK Productivity Toolを使った方法を使えば、自分の欲しい機能は作れてしまうので話は終わるのですが、自分の備忘録を兼ねて調べたクラス構成を以下に書きます。

OpenXMLファイルのクラス構成はかなり数が多いため、重要な部分に絞って記載してます。

全体

まずは全体構成です。

PPTXを作成するには、図の下端にあるSlidePart, SlieMasterPartを一番触ることになります。 スライド全体の設定(スライドサイズなど)はSlideMasterPart, 各スライドについてはSlidePartといった分担です。 ThemePartは見た目のデザインを変更するに際にいじることがあり、また図には載せていませんが、スライドレイアウトを使う場合はSlideLayoutも触ることになります。 (今回私の作成した機能は1枚目のタイトルシート以外は全てBlankスタイルのシートを使っているので、スライドレイアウトについては触れていません)

Slie

次はスライドです。PowerPointの1枚のスライドに相当するためSlidePartクラスのインスタンスはページ数とイコールになります。

上記図は以下の機能を実装する際に重要になってくるクラスのみを抜き出しています。

  • テキストボックスの配置
  • イメージの挿入
  • 表の挿入

基本的にスライド内に張り付けるオブジェクトは全てShapeTree配下にぶら下がるようです。 一番多用するテキストボックスは、この図の中ではShapeTree以下のShapeに該当します。 Pictureがイメージになり、GraphicFrameが表です。

SlidePartにぶら下がっているImagePart, HyperlinkRelationshipはShapeTree配下にはおりませんが、これは意味があってOpenXMLでのイメージ、ハイパーリンクは実際の描画オブジェクトとは別に実体が埋めこまれており、使う際には実体のIDを参照してイメージの貼り付けなどを行います。 そのため同じ画像ファイルを複数個所で使用する場合は、1つのImagePartに対して、それを参照する複数のPictureができることになります。 ただしこれらは全てSlidePart以下ですので、別シートにイメージを追加する場合はまたImagePartを追加する必要があるように思います(シートをまたいだ参照とかできるのかな。。。)

Shape

次はShapeです。今回はテキストボックスしか利用してませんが、名前からいってその他の図形もこの部分で対応するのかなと思ってます。

今回テキストボックスで実現したかった機能は以下の通りです。

位置、サイズはTransform2Dにて行います。これによく似たクラスでTransformがあり、このあと出てくる表ではそちらが使われているようです。 テキスト自体の設定はTextBody以下で行います。 ParagraphPropertiesにて、横位置のアライン(Left, Centet, Right)と箇条書き設定を行います。 箇条書きについては通常の箇条書きについては、BulletFontとCharacterBulletで設定し、数字のインクリメントタイプの箇条書きについてはBulletFontとAutoNumberedBulletで設定します。 箇条書きをしない場合は、NoBulletを設定します。

テキストボックス内の文字の設定はRunで行います。複数Runを作成することで1つのテキストボックス内にフォント設定の異なる文字列を混在させることができます。

ハイパーリンクはRunPropertiesに対して設定することができ、使う場合は事前に埋め込んだHyperlinkRelationshipのIDをHyperlinkOnClickのIdに指定します。

テキストボックスの背景色や、フォントの前景色はSolidFillで指定でき決められた色での指定やRGB値での指定ができます。(グラデーションの場合はSolidFillとは違うクラスで表現するのかも)

Image

次はイメージです。 事前にImagePartオブジェクトを作成しておく必要があります。 ImagePartオブジェクトにはStreamを指定できるのでSystem.IO.FileStreamなので画像ファイルを読み込んだ後そのままオブジェクトを作成できます。

テキストボックスと同じくTransform2Dにて位置、サイズを指定します。 画像の指定はBlipのEmbedプロパティに事前に作成したImagePartのIDを指定します。 必要あればStretchに引き伸ばし方式の指定ができるようです。(今回私は利用していないので詳しくは調べていません)

Table

最後に表です。長いですがテキストボックスと同じ部分もあるので新たに出てくるオブジェクトはそこまで多くないです。

位置とサイズはTransformオブジェクトで行います。(Transform2Dではない) タイトル行のありなしなどは、TablePropertiesにて設定可能です。

実際に表を作成するには、まずTableGridに列の数だけGridColumnを追加します。その際列の幅も一緒に指定できます。 次にTableにTableRowを行数分追加していきます。TableRowには行の高さを指定できます。 表のセルはTableRowに対してTableCellを追加していくことで実装します。 TableCellの中身はテキストボックスの時のTextBody以下とほぼ一緒です。

あとがき

今回はOpenXML SDKを使ってPowerPointファイルを作成する際のやり方に対して自分の学んだ内容を書きました。 今回触れていないアニメーションの追加や、各種図形の追加なども試してはいませんがOpen XML SDK Productivity Tool を使って解析していけば同じようにできると思っています。ほんとこのツールは便利です。

PowerPointのファイル出力機能をC#アプリに追加してみたい方は参考にしてください。


See also