見出し画像

マクロのある暮らし(15回目) - 図形でアニメーションしよう

こんにちは!なるーらぼです!
きょうは少し天気もよくなって、昨日よりは暖かそうですね。
午後から岡山県は雨の予報なので傘が必要かな…?

図形

今回は図形です。ExcelにしてもPowerPointにしても、使わない日はない!という方も多いのではないでしょうか?

この図形もマクロから扱うことができます。「Shape」オブジェクトです。前回のグラフのときにも登場しました。図形はシートごとにShapesコレクションで管理されています。前回はグラフでしたので「AddChart2メソッド」を利用しましたが、今回は「AddShapeメソッド」を利用します。

今回調べてみて気づいたのですが、ExcelとPowerPointで同じ名前のメソッドは違いがないみたいですね。それは助かりますね。
引数には1つ目にどの図形を入れるかを指定します。選択肢はExcelなんかで図形挿入するときに出てくるアレです。

どの図形がどれなのかは一覧がありますのでURLを記載しておきますね。

MsoAutoShapeType 列挙 (Office)

あとは図形の左からの位置、上からの位置、幅、高さをポイント単位で指定します。こんな感じです。

Dim moon As Shape
Set moon = ActiveSheet.Shapes.AddShape(msoShapeMoon, 162, 55, 145.5, 135)

AddShapeメソッドはShapeオブジェクトを返すので、これを利用してスタイルや形を整えていきます。

With moon
 .ShapeStyle = msoShapeStylePreset61
 .Adjustments.Item(1) = 0.13918
 .Flip msoFlipHorizontal
End With

「ShapeStyle」プロパティで図形の書式設定をします。いい感じの書式をつけてくれるアレです。

「Adjustments」オブジェクトは図形を選択したときに表示される黄色の点を表します。1から始まるインデックス番号で選択して形を調節します。この選択できる数は図形によって異なりますが、最大で8個までです。

上記のコードではFlipメソッドを使っていますが、これは左右や上下の図形向きを反転するもので、ここでは左右方向として「msoFlipHorizontal」を指定しています。上下の場合は「msoFlipVertical」になります。

さらに、何ポイントずつ移動させるかなどは次のようにすると指定できます。

moon.IncrementLeft 20

これは左右方向の位置を調整するもので、左からの位置を20ポイントずらすということになります。これをApplication.Waitと組み合わせるとアニメーションすることが期待できます。

例えば、こんな感じです。

Dim i, x As Integer
For i = 1 To 10
 moon.IncrementLeft 20
 ActiveSheet.Calculate
 Application.Wait TimeSerial(Hour(Now), Minute(Now), Second(Now) + 1)
Next

この例では10秒かけて20ポイントずつ右へ移動していきます。

アニメーション

ところで、上記のようにさせると10秒かけて200ポイント動きますが、ひとつ問題があります。

Application.Waitメソッドは最低単位が秒です。そして、このメソッドが動作している間は実行されているマクロがExcelなどの処理を優先的に独占します。ですから、アニメーションとしてはいまいちです。

ということで、ほんの少し背伸びをしましてWindows APIを利用してみたいと思います。Windows APIというのはプログラムからWindowsそのものを操作するために用意されたもので、ほぼすべてのWindowsプログラムはこのAPIを内部的に利用しています。今回はこのうちの「sleep関数」というものを使って指定時間だけ処理を停止してもらおうと考えています。

Windows APIを利用するためには、最初に「使いますよー」という宣言が必要になります。標準モジュールへ次のように追記します。

Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

なんやこれ?という感じですが、気にせず使い方を見てみましょう。

Sleep 10

こんな感じで使います。ん?普段の関数なんかと何が違うん?
はい、見た目は違いません。しかし引数に与えている10という数値の単位は秒ではありませんミリ秒です。ですから上記のコードは「10ミリ秒だけ処理を停止して」という命令になります。しかも命令する先はExcelVBAではなくWindowsそのものです。

こうすると処理はさほど重くならずに10ミリ秒単位なので滑らかにアニメーションするようになります(注:実際にはループ回数と再描画回数が10倍になっているのでCPUは使いますが)。

Dim i, x As Integer
For i = 1 To 100
 moon.IncrementLeft 5
 DoEvents
 Sleep 10
Next

最後に

今回は図形を使ってアニメーションさせてみました。
以下のような感じでApplication.Waitを使ったときとsleep関数を使ったときの動きを比較してみています。

コードも2つのバージョンで掲載しておきます。

https://gist.github.com/nalulabo/65e7f1d95c13d94cc15c6ff175762de0

まだまだ基本的なことであそべますね!

この記事が気に入ったらサポートをしてみませんか?