PowerPointで絶対にプレゼンの時間を遵守させるツールを作る

## はじめに

この記事は[富士通クラウドテクノロジーズ Advent Calendar 2020](https://qiita.com/advent-calendar/2020/fjct)の10日目の記事です。

昨日は@zombeanさんによる[若輩情シスが思う3つの大切なこと](https://qiita.com/zombean/items/af14ab561a5ad15b3a5f)でした。
社内システムの安全を守りつつ、より良くしようとしてくれている情シス......頭が下がる思いです。今後ともよろしくお願いします。

## 本題

みなさまプレゼンしてますか？
私はテレワークが増えてオンラインでプレゼンすることが多くなりました。世の中って変わるものですね。

プレゼンの方法は変わりつつあるかもしれませんが変わらないものもあります。

そう、プレゼンの持ち時間です。

今日はパワポのVBAプロジェクトを使ってそんな持ち時間を遵守するためのツールを作る方法をご紹介します。
これで時間を守らない偉い人のプレゼンを駆逐しましょう

### 何を作るのか

Rabbit、のパワーポイント版を作成します。
Rabbitに関しては下記公式を参照
https://rabbit-shocker.org/ja/

簡単に説明すると、「スライドの現在のページ数÷総ページを表すうさぎ」と「現在のプレゼン秒数÷合計プレゼン時間を表すかめ」をページ下部に表示することで、発表者が現在のプレゼン進捗を一目で把握できるようにします。
下記のような画像をプレゼンの下部に埋め込むイメージです。
うさぎの方が先行している場合「やや早めにプレゼンが進んでいる」、かめの方が先行している場合「やや遅めにプレゼンが進んでいる」という判断ができます。

![usakame.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200826/367ca9a1-566f-609d-9d9c-35df3afd19d2.gif)

### パワポマクロを作成する うさぎ編

まずはパワポのマクロを作成します。
下記のボタンを押下してマクロを作成します。
PowerPointのバージョンはOffice 365を利用しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200826/3235c62b-7ac3-5bd7-58d2-8ed03c38ffb9.png)

まずはうさぎ用のマクロを作成しましょう。「うさぎ実行」という名前で作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200826/7df34546-7fb9-a5a1-1a7f-2ccfa45d6bcc.png)

作成すると、VBAプロジェクトの画面が開くと思います。
表示された画面に以下を記述しましょう。

```
Sub うさぎ実行()
    On Error Resume Next
    
    For i = 1 To ActivePresentation.Slides.Count
        For Each sh In ActivePresentation.Slides(i).Shapes
            If sh.Name = うさぎ名 Then
                sh.Left = (i - 1) * (ActivePresentation.PageSetup.SlideWidth / ActivePresentation.Slides.Count)
            End If
        Next
    Next
End Sub

Function うさぎ名() As String
    うさぎ名 = "うさぎ"
End Function
```

簡単に解説します
２つの関数を定義していますが、重要なのは一つ目の「うさぎ実行」です。
これが実行されると、すべてのページにうさぎの画像を配置します。
画像が配置される位置は、現在のページ数÷総ページ数で計算されます。
もしページの総数が3ページだとすると下記のイメージようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200826/e6451c67-df12-f6ca-bcae-87be0dea7225.png)

ページが進むにつれ、うさぎが進んでいくのがわかります。
うさぎ名の関数に関しては、パワポ内のどの画像がうさぎなのか？の判断に使います。
名前の付け方については後述します。
うさぎのマクロに関してはこれで完成です。

### パワポマクロを作成する かめ編

うさぎと同様に新たなマクロを作成します。「かめ実行」という名前でマクロを作成しましょう。
作成後、VBAプロジェクトの画面で以下を記述しましょう。

```
Sub かめ実行(totalSec As Integer, startTime)
    On Error Resume Next
    Dim secCount As Integer
    Dim tmpTime As Integer
    secCount = (Minute(Now - startTime) * 60) + Second(Now - startTime)
    tmpTime = 0
    
    'カウント処理。かめを動かす
    Do While totalSec >= secCount
        DoEvents
        If (tmpTime <> secCount) Then
            tmpTime = secCount
            For Each sld In ActivePresentation.Slides
                For Each sh In sld.Shapes
                    If sh.name = かめ名 Then
                        sh.IncrementLeft (ActivePresentation.PageSetup.SlideWidth / totalSec)
                    End If
                Next
            Next
            
            If (ActivePresentation.SlideShowWindow.Active = msoTriStateMixed) Then
                Exit Do
            End If
        End If

        secCount = (Minute(Now - startTime) * 60) + Second(Now - startTime)
    Loop
End Sub

Function かめ名() As String
    かめ名 = "かめ"
End Function
```

うさぎよりも少し複雑ですね、簡単に解説します。
まず、かめが動作するためには、「プレゼン完了の予定秒数」を先に定義する必要があります。
プレゼン開始時にダイアログ等で入力させるのが手っ取り早いと思います。
今回は、それがすでに引数にわたってくる前提で、 `totalSec` が「プレゼン完了の予定秒数」です。
「現在の秒数」と「プレゼン完了の予定秒数」に応じて、リアルタイムでかめの位置を更新していきます。

細かく解説しませんがキモになるのは `DoEvents` です。
これは、OSに処理を一旦渡すための関数で、記載しないとパワポが応答なしの状態になってしまいます。

また、 `ActivePresentation.SlideShowWindow.Active` の状態を見てマクロを終了する処理も大事です。
これがないと、スライドショーが実行されていない間もマクロが動き続けてしまいます。

実行すると、スライドショー中にカメがリアルタイムにじわじわと動いてくれます。
![かめ.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200826/638a4bb2-26b0-7021-0cc5-2499df5b52be.gif)

かめ名の関数に関してはうさぎと同様、どの画像がかめかを判断するために使います。後述します。

### パワポマクロを作成する スライドショー開始ダイアログ編

VBAプロジェクトの画面から、「ユーザーフォーム」を作成しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200826/6e7a31f9-eba9-1938-0b6a-b876c0e69b80.png)

「プレゼン完了の予定秒数」を入力してスライドショーを開始しつつ、うさぎ実行、かめ実行をそれぞれ実行するためのダイアログを作ります。
最終的にこれを実行することで、プレゼンを始めていくわけですね。
私は以下のようなフォームを組み立てました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200826/dc914258-dbba-6cfb-e6db-fb8104a26b6d.png)

また、フォームに紐づくコードは以下で実装しています

```
Private Sub StartButton_Click()
    Dim totalSec As Integer
    Dim startTime

    totalSec = MinutesSpinButton.Value * 60 + SecondSpinButton.Value
    startTime = Time
    
    RabbitAndTurtle.Hide
    
    Call うさぎ.うさぎ実行
    Call かめ.かめ実行(totalSec, startTime)
    
End Sub

Private Sub MinutesSpinButton_Change()
    With MinutesSpinButton
        .SmallChange = 1
    End With
    MinutesBox.Value = MinutesSpinButton.Value
End Sub

Private Sub SecondSpinButton_Change()
    With SecondSpinButton
        .SmallChange = 10
        .Max = 50
    End With
    SecondBox.Value = SecondSpinButton.Value
End Sub
```

こちらはあまり複雑ではないですね、分と秒の計算をしてうさぎ実行、かめ実行を呼び出すくらいです。
あと、startが押されたらフォームを非表示にするのを忘れずに。 
これでスライドショーを開始するダイアログは完成です。

### パワポマクロを作成する うさぎとかめに名前を付ける編

うさぎ実行、かめ実行では、うさぎとかめの画像をスライド内で操作しています。
操作するためには、スライド内のオブジェクトを「うさぎ」「かめ」として指定する必要があります。
うさぎ実行、かめ実行では、画像の「名前」を見て「うさぎ」「かめ」の画像を判断しています。
そのための名前を付けるVBA関数がこちら

```
Sub 選択中のオブジェクトをうさぎに設定()
  On Error Resume Next
  ActiveWindow.Selection.ShapeRange.name = うさぎ.うさぎ名
End Sub

Sub 選択中のオブジェクトをかめに設定()
  On Error Resume Next
  ActiveWindow.Selection.ShapeRange.name = かめ.かめ名
End Sub

Sub 選択中のオブジェクトをうさかめから解除()
  On Error Resume Next
  ActiveWindow.Selection.ShapeRange.name = "NoName"
End Sub
```

`ActiveWindow.Selection.ShapeRange.name` がここで言っている「名前」ですね
うさぎ実行、かめ実行の関数は"うさぎ"と"かめ"の名前の付いた画像を操作します。
任意の画像を選択しつつ、これらの関数を呼び出すことで、うさぎ、かめとして動かすことができます。
この名前を付けた画像をすべてのスライドに配置しておきましょう。

### 完成！

これでパワポ版Rabbitは完成です！
このマクロを利用して時間をまもったプレゼンをしましょう

・・・とはいえ、このマクロを作成した端末でしか、マクロは実行できません。
時間を守ってくれない人の端末でこのマクロを書くのは現実的じゃないですよね

以下にアドイン用のファイルを公開しています。
それをダウンロードしていただき、読み込むことで簡単に利用が可能です。お試しください。
https://github.com/nashik/usakame

## 最後に
Excelの陰に隠れてあまり使われないパワポVBAですが、そんなものもあると気に留めておくと今後もしかしたら何かの役に立つかもしれません。
アドベントカレンダー次の日は@tanopantaさんです。お楽しみに！