PowerPointアドインを作る手順の概要
0. はじめに
本記事はPowerPointアドインの作成記録である。現状、PowerPointアドインの作成方法の流れを丁寧に解説した記事は残念ながらほとんどない。筆者は苦心の末にアドインの作成に成功したので、後の人のために、丁寧に解説という目標は果たせていないかもしれないが、とりあえず一連の流れを残すことにした(完璧を目指すよりまず終わらせろの精神で)。単にアドインを作成するのでなく、それを定期的に更新することを見据えている。
アドインにはC#を用いるものとVBAを用いるものとがあるが、後者の方が作成が簡単であるようなので(ただし柔軟性には劣るのかもしれない)、VBAを利用する。
なお、巷ではアドインを作成するにあたって「Custom UI Editor」「Office RibbonX Editor」などのGUI補助ツールが紹介されているが、ここではPowerPointアプリ(VBAエディタ含む)と汎用テキストエディタのみを用いて作成できるようになることを目指す。
本記事はVBAについては既にある程度知識のあることを前提とする。つまり、当然ながら、簡単なマクロを作成できる程度の技能がなければ自作アドインを作ることはできないが、VBAの解説は既に無数に存在するのでここでは説明しない。PowerPointマクロ(Excelでもいいが)に馴染みのある人ならば問題ないだろう。
1. アドインファイルの構造を知る
1.1. .ppam
ファイルを作る
PowerPointアドインファイルは.ppam
という拡張子を持つ。とりあえずこのファイルがどういうものなのかを見てみよう。
とりあえず空白の.ppam
ファイルを作ることにする。具体的に説明すると、
- PowerPointファイルを新規作成
- メニューの「開発 > コード > Visual Basic」(または
Alt + F11
)でエディタ立ち上げ - プロジェクトウィンドウで右クリックして「挿入 > 標準モジュール (M)」
- スクリプトは空白のままエディタを終了
- パワポファイルを名前をつけて保存、その際にファイルの種類を
PowerPoint アドイン (*.ppam)
にし、任意の場所に保存
※手順5でファイルの種類をPowerPoint アドイン (*.ppam)
にすると、保存場所のデフォルトがアドインを最終的に配置するアドレスになる。今は編集段階なのでここには保存しないほうが良いだろう。
保存したファイルの拡張子を.ppam
から.zip
に変更して、解凍すると、おそらく次のようになっている。
ppamファイル
│ [Content_Types].xml
│
├─ppt/
│ │ presentation.xml
│ │ vbaProject.bin
│ │
│ └─_rels/
│ presentation.xml.rels
│
└─_rels/
.rels
./ppt/vbaProject.bin
がスクリプトの本体で、上記の手順の4でスクリプトになにか適当なマクロを書いてから(コンパイルエラーに注意)保存すると、このファイルのサイズが変わっていることがわかるだろう。
逆に、スクリプトになにを書いてもvbaProject.bin
以外のファイルは何も変わらないはずである。
1.2. .ppam
ファイルの構造
上で見た.ppam
ファイルにはリボンの定義が存在しない。最終的に我々が作るものは、リボンに関するファイルが詰め込まれたcustomUI
フォルダが追加されることになる。
結論を先取りすると、我々が作る.ppam
ファイルは最終的に以下のような構造になる。
ppamファイル
│ [Content_Types].xml
│
├─customUI/
│ │ customUI14.xml
│ │
│ ├─images/
│ │ ~~~.png
│ │
│ └─_rels/
│ customUI14.xml.rels
│
├─ppt/
│ │ presentation.xml
│ │ vbaProject.bin
│ │
│ └─_rels/
│ presentation.xml.rels
│
└─_rels/
.rels
全てのファイルについて簡単に説明する。
-
./[Content_Types].xml
: 全体の定義(ほぼ編集不要) -
./customUI/customUI14.xml
: リボンの定義 -
./customUI/images/~~~.png
: アイコンの画像ファイル(任意) -
./customUI/_rels/customUI14.xml.rels
: アイコンの定義 -
./ppt/presentation.xml
: 知らん(編集不要) -
./ppt/vbaProject.bin
: VBスクリプトがコンパイルされたもの -
./ppt/_rels/presentation.xml.rels
: 知らん(編集不要) -
./_rels/presentation.xml.rels
: 知らん(編集不要)
前節で見たように、./ppt/vbaProject.bin
(と今説明した./customUI/
フォルダ)以外のファイルは共通であるため、基本的に触る必要がない。ただし./[Content_Types].xml
については「俺はリボン定義するぞ」という行を追加する必要がある。詳細は追って説明する。
2. どのように.ppam
ファイルを作るか
§1.1で見たように、PowerPointでVBAエディタを立ち上げてそこにスクリプトを書き、.ppam
として保存すれば完成とはいかない。なぜなら、PowerPointアプリ(VBAエディタ含む)の中ではリボンUIに関する設定ができず、さらに、一度作成した.ppam
ファイルを直接編集することすらできないからである。
そこで、まず§1.1の方法で./customUI/
フォルダ以外の部分を作成し、./customUI/
フォルダの中身のファイルについては別途テキストエディタで(アイコンは適宜画像編集ソフトで)作成することとする。
このようにして各ファイルを個別に作成した後、§1.2の通りの構造でファイルを配置する。それを.zip
で圧縮し、最後に拡張子を.ppam
にを変更すれば完成である。
以下、作成手順を簡単に手順を説明する(ここでは作業手順のみを紹介し、各ファイルに何を記述すれば良いかについては後述する)。まずは§1.1の要領で.ppam
ファイルを作成して解凍、作業フォルダに配置する。
任意の作業フォルダ
│
└─my_addin/
│ [Content_Types].xml
│
├─ppt/
│ (略)
│
└─_rels/
.rels
2.1. [Content_Types].xml
の修正
手始めに[Content_Types].xml
を修正する必要がある。
[Content_Types].xml
を開くと次のようになっているはずである。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="bin" ContentType="application/vnd.ms-office.vbaProject"/><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Override PartName="/ppt/presentation.xml" ContentType="application/vnd.ms-powerpoint.addin.macroEnabled.main+xml"/></Types>
中身を以下に入れ替える。改行を追加したためめちゃくちゃ変わっているように見えるかもしれないが、実際には4行目(Extension="png"
の行)を追加しただけである。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default Extension="bin" ContentType="application/vnd.ms-office.vbaProject"/>
<Default Extension="png" ContentType="image/.png"/>
<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
<Default Extension="xml" ContentType="application/xml"/>
<Override PartName="/ppt/presentation.xml" ContentType="application/vnd.ms-powerpoint.addin.macroEnabled.main+xml"/>
</Types>
この作業は、次節以降で紹介するものと違って、一度行えば以降[Content_Types].xml
の編集は不要である(アドインの中身を更新するたびに手を加えるということはないという意味)。自作アイコンを全く使わない場合には、この[Content_Types].xml
の編集作業は不要かもしれない。
2.2. スクリプト本体(vbaProject.bin
)
2.2.1. vbaProject.bin
の編集方針
vbaProject.bin
はスクリプト本体が格納されたアドインの「核」なので、この編集作業はおそらく最も頻繁に行う作業である。
しかし§2で軽く触れたが、PowerPointアプリ(VBAエディタ含む)で.ppam
ファイルのスクリプトを直接編集することはできない。この問題の解決策は、.pptm
ファイルを使うことである。.pptm
ファイルは通常のパワポ(.pptx
)にマクロ機能を備えたもので、エクセルで言えば通常.xlsx
に対するマクロ付き.xlsm
に相当する。
.pptm
ファイルを.zip
ファイルとして開いて中身を見ると、その構造は.ppam
にスライド情報が追加されただけでほとんど同じであることがわかる。.pptm
ファイルはPowerPointアプリ(VBAエディタ)で直接編集できるので、スクリプトの保存・編集が簡単にできる。.pptm
ファイルのスクリプトを編集したら、vbaProject.bin
を抽出して作業フォルダに貼り付けるのである。
2.2.2. vbaProject.bin
を編集するための.pptm
ファイルの配置
では、§1.1の方法で作業フォルダ直下に今度は.pptm
ファイルを保存しよう。名前はもちろんなんでも良いが、説明のためにここではvbs.pptm
として保存した。VBAエディタ以外でスクリプトを編集したい人や、特にスクリプトをgit等で管理したい人は(二度手間になるが).bas
ファイルを別途保存してもよいだろう。
任意の作業フォルダ
+ │ vbs.pptm
+ │ vbs.bas (任意)
│
└─my_addin/
│ [Content_Types].xml
│
├─ppt/
│ (略)
│
└─_rels/
.rels
この.pptm
内のスクリプトに記述する内容の詳細については後述するが、例えば空白の状態から次のように追記したとしよう。
Private myRibbon As IRibbonUI
' onLoad関数
Public Sub myRibbonOnLoad(ribbon As IRibbonUI)
Set myRibbon = ribbon
myRibbon.Invalidate
End Sub
' 右移動(※選択したオブジェクトを右に100pt移動させるだけの関数)
Public Sub MoveRight()
Dim SelectedShapes As ShapeRange
' オブジェクト以外が選択されている場合は無視する
If ActiveWindow.Selection.Type = ppSelectionNone _
Or ActiveWindow.Selection.Type = ppSelectionSlides Then
Exit Sub
End If
' 移動
SelectedShapes.IncrementLeft 100
End Sub
.pptm
の編集が終わったら上書き保存してパワポアプリを終了し、その.pptm
ファイルを.zip
ファイルとして開き、./ppt/vbaProject.bin
をコピーして作業フォルダの同じ位置(この記事の例では任意の作業フォルダ/my_addin/ppt/vbaProject.bin
)に貼り付ける。この作業はスクリプトを編集するたびに行う必要がある(以降、この作業手順を行う必要があることは省略する)。
2.3. CustomUI
フォルダの作成
§1.2で触れたように、このままだとリボンUI要素が足りていない。アドイン本体となるフォルダ(本記事の例では任意の作業フォルダ/my_addin/
フォルダ)の下にCustomUI
フォルダを追加し、その下に_rels
フォルダとimages
フォルダを追加する。
任意の作業フォルダ
│ vbs.pptm
│ vbs.bas (任意)
│
└─my_addin/
│ [Content_Types].xml
│
+ ├─CustomUI/
+ │ │
+ │ ├─images/
+ │ │
+ │ └─_rels/
+ │
├─ppt/
│ (略)
│
└─_rels/
.rels
2.4. ツールアイコン
リボンに表示するアイコンを.png
形式で作成し、images
フォルダに投入する。アイコンに合わせてCustomUI/_rels/customUI14.xml.rels
を編集する。
任意の作業フォルダ
│ vbs.pptm
│ vbs.bas (任意)
│
└─my_addin/
│ [Content_Types].xml
│
├─CustomUI/
│ │
│ ├─images/
+ │ │ icon1.png
+ │ │ icon2.png
│ │
│ └─_rels/
+ │ customUI14.xml.rels
│
├─ppt/
│ (略)
│
└─_rels/
.rels
2.5. リボンUIのデザイン
リボンのデザインを定義したcustomUI14.xml
をCustomUI
フォルダの下に作成する。
任意の作業フォルダ
│ vbs.pptm
│ vbs.bas (任意)
│
└─my_addin/
│ [Content_Types].xml
│
├─CustomUI/
+ │ │ customUI14.xml
│ │
│ ├─images/
│ │ icon1.png
│ │ icon2.png
│ │
│ └─_rels/
│ customUI14.xml.rels
│
├─ppt/
│ (略)
│
└─_rels/
.rels
中身についての詳細は後述するが、とりあえず最小限の内容として次のように書いておく。
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="">
<ribbon startFromScratch="false">
<tabs>
</tabs>
</ribbon>
</customUI>
2.6. 作成完了
(この説明でいう)my_addin
フォルダを圧縮して.zip
ファイルにし、拡張子を.ppam
に変更すれば完成である。
実際に使用する際の手順は以下の通り。
-
%APPDATA%/Microsoft/AddIns
(つまりC:/Users/ユーザー名/AppData/Roaming/Microsoft/AddIns
)に.ppam
ファイルをコピー - PowerPointアプリを開き、「ファイル > オプション(一番左下) > “アドイン”タブ > 管理:Powerpointアドイン > 設定(G)」でアドイン設定画面を開く
- 「使用可能なアドイン」に作成したアドインがない場合、「新規追加」を押して1.で追加したファイルを選択
- 追加したアドインにチェックを入れて「閉じる(C)」
3. onLoad関数の設定
§2で各ファイル・フォルダを正しい位置に配置できたので、あとは各ファイルを必要に応じて編集するだけである。
さて、パワポアプリを立ち上げたときにリボンを読み込んで表示するための関数を定義する必要がある。これを自分はonLoad関数と呼んでいる。
onLoad関数でやることは、引数名ribbon
でIRibbonUI
型オブジェクトを受け取って、その.Invalidate
メソッドを実行するだけである。以下のコードをスクリプトにコピペしよう(myRibbon
の部分は任意の名前でよい)。
Private myRibbon As IRibbonUI
Public Sub myRibbonOnLoad(ribbon As IRibbonUI)
Set myRibbon = ribbon
myRibbon.Invalidate
End Sub
onLoad関数をスクリプトに書いたら、customUI14.xml
の1行目のonLoad=""
の部分にその関数の名前を書く。
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="myRibbonOnLoad">
<ribbon startFromScratch="false">
<tabs>
</tabs>
</ribbon>
</customUI>
4. リボンの設定
4.1. リボンの基礎
リボンは階層構造になっている。下図は最初からあるホームタブのキャプチャである。その「タブ」の中に、下図青枠で囲った「グループ」があり、さらにグループの中にオレンジ枠で囲った「ボタン」がある。
ボタンには大中小3種類のサイズがある。上図の「貼り付け」「新しいスライド」は大サイズで、32x32サイズのアイコンの下にラベルが表示される。「切り取り」「コピー」などは中サイズで16x16サイズのアイコンの横にラベルが表示される。上図で見切れている文字の太字斜体下線ボタン(16x16サイズのアイコンのみでラベル無し)が小サイズである。
中サイズと小サイズは縦に3つ並べることができるが、大サイズはそれだけで3段分消費するので縦に並べることはできない。横にはどのサイズのアイコンも無限に並べることができる。
リボンUIは、これらの情報を含めてcustomUI14.xml
で設定する。下記のように、タブの中にグループがあり、グループの中にボタンがある。タブ、グループ、ボタンは固有のID(id
)をもたせる必要がある。それ以外の属性については以降で説明する。
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="positionsRibbonOnLoad">
<ribbon startFromScratch="false">
<tabs>
<tab id="mytab1">
<group id="mygroup1">
<button id="mybutton1" />
</group>
</tab>
</tabs>
</ribbon>
</customUI>
4.2. タブの設定
タブは下記のように<tab></tab>
を適切な位置(<tabs>
~</tabs>
の間)に配置することで設定する。ところで個人的には、1つのアドインに複数のタブをもたせることは、無意味に複雑化させていると感じるため推奨しない。2つのタブには2つのアドインを別々に作ったほうが良いだろう。
<tab>
の中に以下の属性を記入する。
-
id
= 固有のID -
label
= 表示されるラベル -
keytip
= アクセスキー。Powerpointアプリにおいて、Alt
キーを押したあとにここで設定したキーを押すとこのタブにジャンプできる。設定されているキーはAlt
長押しで確認できる。単一のキーでは、A
,B
,C
,F
,G
,H
,K
,L
,N
,Q
,R
,S
,W
と数字はデフォルトで使われているようだ。
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="positionsRibbonOnLoad">
<ribbon startFromScratch="false">
<tabs>
<tab id="mytab1" label="タブ1" keytip="T">
……
</tab>
</tabs>
</ribbon>
</customUI>
4.3. グループの設定
グループは下記のように<group></group>
を適切な位置(<tab>
~</tab>
の間)に配置することで設定する。
<group>
の中に以下の属性を記入する。
-
id
= 固有のID -
label
= 表示されるラベル。§4.1の図でいう「クリップボード」や「スライド」がそれである。 -
image
= アイコン画像。§4.1の図を見ればわかるようにデフォルトでは表示されないが、クイックアクセスツールバーにグループを登録すると表示されるので設定した方が良い。
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="positionsRibbonOnLoad">
<ribbon startFromScratch="false">
<tabs>
<tab id="mytab1" label="タブ1" keytip="T">
<group id="mygroup1" label="グループ1" keytip="A">
……
</group>
</tab>
</tabs>
</ribbon>
</customUI>
4.4. ボタンの設定
ボタンは下記のように<button />
を適切な位置(<group>
~</group>
の間)に配置することで設定する。
<button>
の中に以下の属性を記入する。
-
id
= 固有のID -
onAction
= ボタンを押したときに動かす関数 -
label
= 表示されるラベル。§4.1の図でいう「切り取り」や「貼り付け」がそれである。 -
image
= アイコン画像。大サイズでは32x32、中小サイズでは16x16で表示される。 -
keytip
= アクセスキー、すなわちタブのアクセスキーの次に求められる入力。(任意) -
size
= 表示サイズ(§4.1参照)、large
,
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="positionsRibbonOnLoad">
<ribbon startFromScratch="false">
<tabs>
<tab id="mytab1" label="タブ1" keytip="T">
<group id="mygroup1" label="グループ1" keytip="A">
<button id="mybutton1" onAction="myfunc1" label="ボタン1" image="SwapIcon" size="large"/>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
このボタンが押されると、onAction
で指定したVBスクリプトの関数が動くことになる。
4.6. ボタン以外(例えばチェックボックス)の設定
リボンにはボタン以外のオブジェクトを配置することができる。ここでは例としてチェックボックスを紹介しよう。
チェックボックスの実装は、リボンへ配置するのは簡単だが、VBスクリプトへにおける記述がやや難解である。そこには、「onAction関数」(すなわちチェックボックスを押下したときに発動する関数)に加えて、「チェックボックスの状態を格納する変数」「getPressed関数」を準備する必要がある。
- チェックボックスは常に「
True
:チェックが入っている状態」「False
:チェックが入っている状態」のどちらかの状態でなければならない。この状態を格納する変数(以下の例ではcheckBoxState
)をBoolean
型で定義する。 - 常にどちらかの状態でなければならないとは、リボンが読み込まれるonLoad関数の
myRibbon.Invalidate
よりも前にデフォルトの状態(例ではFalse
)を設定しなければならないということである。 - getPressed関数(例では
checkBoxFunc_getPressed
)は、状態を格納した変数をそのまま返すだけの関数。これは変数の状態を実際にリボンに反映させる役割を持つ。 - onAction関数は、getPressed関数とは逆に、ボタンが押されたとき(すなわちチェックボックスの状態が変わったとき)にリボンの状態を取得して変数に格納させる役割を持つ。
pressed
引数を受け取って変数に代入する。
Private myRibbon As IRibbonUI
Private checkBoxState As Boolean '←チェックボックスの状態変数
' onLoad関数
Public Sub myRibbonOnLoad(ribbon As IRibbonUI)
Set myRibbon = ribbon
checkBoxState = False '←チェックボックスのデフォルト値の設定
myRibbon.Invalidate
End Sub
' getPressed関数
Public Sub checkBoxFunc_getPressed(control As IRibbonControl, ByRef RetVal)
RetVal = checkBoxState
End Sub
' onAction関数
Public Sub checkBoxFunc_onAction(control As IRibbonControl, pressed As Boolean)
checkBoxState = pressed
End Sub
状態を格納した変数(上の例のcheckBoxState
)を他の関数のIF条件にすれば、チェックボックスの状態に合わせて異なる挙動を示す関数を作ることができる。
リボンUIの設定は、ボタンと同様に<checkBox />
を適切な位置(<group>
~</group>
の間)に配置する。
<checkBox>
の中に以下の属性を記入する。
-
id
= 固有のID -
getPressed
= チェックボックスの状態を保持する変数 -
onAction
= ボタンを押したときに動かす関数 -
label
= 表示されるラベル
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="positionsRibbonOnLoad">
<ribbon startFromScratch="false">
<tabs>
<tab id="mytab1" label="タブ1" keytip="T">
<group id="mygroup1" label="グループ1" keytip="A">
<checkBox id="mycheckbox1" getPressed="checkBoxFunc_getPressed" onAction="checkBoxFunc_onAction" label="チェックボックス" />
</group>
</tab>
</tabs>
</ribbon>
</customUI>