PowerPointの画像や動画をランダムに入れ替えたい

以前、PowerPointでデジタルサイネージを作り、様々な情報をローコストで社内で配信する環境を作りました。PowerPoint自体は静的なスライドをただただ垂れ流すだけなので、VBAを使って動的に情報をリアルタイムに取得・生成する仕組みにする事で、高価なサイネージ装置など使わずとも、サイネージは十分実現が可能です。

今回は、特定のフォルダ内にある画像を特定のスライドにランダムに差し替えるものを実装します。風景チャンネルを作って欲しいという事だったのですが、何百枚もスライド作るのは現実的ではないので、VBAで操作してみたいと思います。

今回使用するパワーポイントファイル

コード編集時は注意が必要です。コードを編集する事で、スライドショー起動時に取得したcntおよびarraymanの中身がクリアされてしまうので、一旦閉じて再度開き直してから、スライドショー実行する必要があります。

事前準備

前回同様、パワポを作るにあたって、色々と事前準備を行います。

ワイド画面対応にする

通常、PowerPointでファイルを作成すると昔のアニメのように4:3で作成されてしまいます。しかし、最近のモニターは16:9で構成されていることが多く、そのままでは画面の両端に黒い帯が出来てしまい、格好が悪い。まずは作り始める前にPowerPointのスライドサイズを16:9のワイド画面対応にしましょう。

  1. デザインタブを開く
  2. スライドのサイズを開く
  3. ワイド画面(16:9)を選択する

図:16:9を使うようにしましょう

VBAを有効にしたpptmファイルにする

今回は動きのある動的なデジタルサイネージコンテンツとするため、ただの紙芝居ではなくVBAを利用するため、今回のファイルはpptx形式ではなく、pptm形式で保存してあげる(でないと、VBAコードを書いても排除されてしまいます)。

  1. ファイルタブを開く
  2. 名前を付けて保存を選択する
  3. 参照をクリックして保存先を選択
  4. その際のファイルの種類について「マクロ有効プレゼンテーション」を選ぶ
  5. 保存ボタンを押す

起動時にセキュリティ警告が出ることがありますが、コンテンツの有効化をクリックしてもらえれば問題ありません。

配置したテキストボックスの名前を調べる

VBAで動的にテキストボックスの値を書き換えたりするのが今回の目的の1つですが、PowerPoint上の各種パーツには表向きプロパティが見えません。しかし、これらのコントロール名が分からなければ、書き換えようがありません。実は表向き見えないだけで、各パーツ類にはきちんと自動でコントロール名が与えられている。

このコントロール名を以下のVBAで事前に調べておき、VBA内で指定して内容を書き換えます。ちなみにこのコントロール名はスライド単位であり、スライドをコピーするとコントロール名も同じ名前のままです。ファイル内では同じコントロール名のボックスがあることになりますが、スライド単位で指定するので、問題なくアクセスが可能です。

  1. 対象のパーツをクリックする
  2. 以下のコマンドを実行する。
  3. パーツの名前とIDが返ってくるので、控えておく。

OnSlideShowPageChangeのバグ対策

PowerPoint VBAを利用する上でぶつかる問題の1つに「スライド変更時にVBAを実行させる」特別なイベントにコードを書いても動かない事がある点です。2013の頃からあるバグで、OnSlideShowPageChangeという関数名で作るとそれが実行可能になっています。スライドの何枚目に来たら実行するのがポピュラーな使い方です。

VBAが実行されない理由はVBAプロジェクト画面にて、標準モジュールしかなく、対象のスライドが見えないというPowerPoint特有の問題があります。この問題の簡単な解決法はどのスライドでも良いので、適当にフォームコントロールを入れてあげること。こうする事でOnSlideShowPageChangeのメソッドがきちんと働くようになります。

  1. 適当なスライドを選択する
  2. 開発タブを開く(表示されていない場合には表示しておきましょう)
  3. ラベルコントロールなどの適当なコントロールを張り付ける
  4. Visual Basicを開く
  5. プロジェクトにSlide〇〇があればOKです。上書き保存しましょう。

図:プロジェクトにSlideがいるのを確認しましょう。

画像の準備

VBAの入ってるPowerPointファイルと同じフォルダ内に「images」というフォルダを作成し、中に適当な画像ファイルを詰め込んで置きます。プログラムは起動時に、このフォルダ内の画像ファイルのパスを配列として格納し、乱数で取り出し差し替えるという仕組みになっています。画像以外のものが混じっているとプログラムが止まりますので要注意。

図形の準備

今回の肝。実はPowerPointで画像の差し替え用のメソッドというものはありません。ただ、VBAとしてImageコントロールを配置した場合には、LoadPictureにて画像のソースを変更出来るとあったのですが、PowerPointではなぜか動かず(UserFormじゃないと動かないのかな)。また、画像を挿入しておいて、そのshapeの画像の入れ替えも頑張ってみましたが、メソッドがないので出来ず。

そこでスライドに何を用意するかと行ったら、図形の四角形(Rectangle)を用意します。これは画像表示用ではないのですが、「背景塗りつぶしで画像が使える」ので、これを利用します。メソッドに「塗りつぶし背景画像の指定」があるので、これで入れ替えるようにします。

図:図形パーツを使うというのがポイント

ソースコード

今回のプログラムでは、スライドショーを開く時イベントである「SlideShowBegin」を使う為、空のリボンを追加します(アドイン形式も出来るけれど、そちらのほうが面倒なので)。

リボンのコード

  • Custom UI Editorを使って作ると楽に作れます。
  • onLoadにOnLoadmanという関数を指定。これがとても重要です。
  • アドインの場合には、Public Sub Auto_Open()にて自動実行をさせる事ができますが、今回はアドイン無しなので使いません。

VBA側のコード(Class1)

SlideShowBeginは、クラスモジュールでなければ作れないので、クラスを追加して以下のようなコードを書きます。スライドショー実行時の1回だけ実行されますが、事前にOnLoadmanで初期化されていないと使えないので、其のためにリボンで自動初期化させています。

  • グローバル変数としてcntおよびarraymanという配列を標準モジュール側で宣言してあります。
  • cntは、指定フォルダ内のファイルの総数を格納。arraymanは指定フォルダ内のファイル名を格納します。
  • 本来は、Dir(Path & "*.jpg")とでもして、jpg画像に絞ったほうが良いのですが、あえて*.*で全ファイル指定にしてあります。
  • スライドショー実行時の1回だけこのコードは実行されます。OnSlideShowPageChangeですと、毎回スライド変更時に動いてしまうので具合が悪い。
  • 最初の1回だけファイル総数とファイル名を取得させておく事で、毎回取りに行く必要がなくなります。
  • 今回はプレゼンファイルの同じフォルダ内にあるimagesフォルダを参照するように、ActivePresentation.Path & "\images\"としています。

VBA側のコード(Module1)

  • 冒頭でClass1のクラスモジュールの呼び込み、グローバル変数のcntおよび配列であるarraymanを定義しています。
  • OnLoadmanはリボン読み込み時に自動実行として指定した関数です。ここでClassを初期化
  • changepict関数が実際に図形の背景画像を書き換える関数。乱数を使って0~画像の数まで生成し、それを基準にarraymanから画像のファイル名を取得させています。
  • 最後の行が画像差し替え。Slides()の数値はスライド何枚目か?ShapesはgetActiveShapeNameで取得した図形の名称を指定。
  • Fill.UserPictureに引数として生成した画像へのパスを渡せばOK.
  • OnSlideShowPageChangeにて、1枚目が開かれたら画像を差し替えるようにchangepictを呼び出しています。

付記

その後、画像も図形ではなく画像をリンク形式で貼り付けて、動画ファイル同様に.LinkFormat.SourceFullNameにて変更できるか?やってみたところ、できちゃいました。手順としては

  1. 画像を埋め込みではなく、リンクで挿入する
  2. パーツの名前をgetActiveShapeNameにて調べておく(例:Picture 4)
  3. 画像を差し替える部分のコードは以下のように記述する。スライド番号は何枚目のスライドなのか数値を、シェイプの名前に2.で調べたパーツの名前を入れます。
  4. pathmanは画像へのフルパス
  5. .LinkFormat.Updateを入れないと反映されないので注意

動画ファイルの差し替えもやってみる

単一ファイルの場合

画像だけじゃなく、ビルなどにあるサイネージのように動画も流したい!!そういう要望もあるでしょう。確かにPowerPointは動画の挿入も可能で、入れ替えが不要なのであれば、以下の手順だけで自動再生が出来るようになります。

  1. 動画ファイルを普通に挿入する
  2. 動画をクリックすると、リボンに「再生」というタブが表示される
  3. 開始の項目を「自動」にする

これだけです。該当のスライドに来ると自動的に再生されます。しかし、画像の時同様にたくさんの動画ファイルがあり、ランダムにとなると当然この方法では不可能です。

図:単一ファイルならばすごく簡単

複数ファイルをランダムに差し替えて再生

複数ファイルの場合はVBAでコードを書く必要があります。今回は動画ファイルはプレゼンファイルの同じフォルダ内に作った「movie」というフォルダ内に格納しておきます(形式は.mp4/H.264/AVCを選びました)。movのファイルをXMedia RecodeにてBitrate2500にてエンコしてます。

Windows Media Playerコントロールを埋め込んで再生するやり方もあるようですが、今回は基本機能のみで実装してます。

VBA側のコード(Class1)

  • こちらは画像の時とほとんど変わりません。グローバル変数のmcntおよびグローバル配列movieman()は、Module1側へ記述しています。

VBA側のコード(Module1)

  • 動画ファイルは埋め込みじゃなく、リンク形式で予め1個スライドに入れておく必要があります。
  • 対象シェイプの名前はgetActiveShapeNameにて予め調べておきましょう。動画をクリックしてから手動で実行するだけで取れます。
  • OnSlideShowPageChangeの1枚目でchangemovを実行し、スライドのリンク先を変更しておく
  • 今回動画は8枚目のスライドに入れてみました。スライド番号は8で、getActiveShapeNameで取得したシェイプ名を入れておく
  • リンク先の差し替えは、.LinkFormat.SourceFullNameにて行います。フルパスを渡します。
  • このままだと自動再生されない。ですので、plyr変数にitemidをセットし、plyr.Playにて再生をさせるようにしています。
  • 途中にDebug.Printが入っていますが、これを入れておかないと何故か自動再生が実行されない。動画自体に自動再生の設定を予めしておいても再生されないです。ですので、このDebug.Printはコードとして必要な行です。
  • 今回の手法はローカルの動画ファイルの再生なので、Youtube貼り付けを変更するものではありません。
  • 動画差し替えはサンプルファイルに含まれていません。。

自動ループ再生の設定

自分のプレゼンファイルは以下のような再生設定で無事に動画入れ替えと自動再生が出来るようになりました。

  1. 動画のファイル自体に「自動再生」の設定は仕掛けてある。
  2. 動画ファイルは再生時は全画面表示に設定してあります。
  3. スライドショーの設定では、種類は「発表者として使用」、オプションは「ESCキーが押されるまで繰り返す」。これで無限ループになります。
  4. 画面切り替えでは、全スライド切り替えタイミングは「自動的に切り替え」にて10秒で設定しています。クリック時は外してあります。
  5. 画面切り替えはスライド毎にも設定できるので、静止画は少なめに、動画は長めに設定すると良いでしょう。
  6. なお、自動プレゼンテーションの場合のループ再生だとうまく行かないことがあります。

図:スライドショー設定

関連リンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)