読者です 読者をやめる 読者になる 読者になる

Powerpoint VBAを使おう!

Powerpoint VBAやExcelのVBAで遊んでいます。Word VBAも始めました。

Powerpoint VBAに興味が沸いた方々へ⑤

ラストです。繰り返し処理(ループ)について。

VBAについてはExcelの書籍が多い。とにかく多い。一冊でもまともなPowerpointVBAの本があってもいいじゃないか,と思いますが無い。
ひとえにPowerpointVBAなどなくても高機能極まりないからだと思います。

でもVBAでしかできないことはある。なのできっかけになりたいところです。

さて本題。同じことを繰り返す方法として3つほど挙げたいと思います。①For ループ ②Do ループ ③For Each ループ,この3つです。
Loop Structures (Visual Basic)
こらちにわかり易く書いてあります。わたしのつたない説明など見ずにそちらを参照するのもいい手です!

①For ループ
BASICという言語がありましたね。あれでよく使われていたループ。
まず例を書きます。せっかくなので使ってなかった配列を混ぜて書きます。
f:id:chemiphys:20170109161031p:plain

Sub test3()
Dim Box(1 To 10) As String
Dim i As Long

For i = 1 To 10
    Box(i) = ActivePresentation.Slides(1).Shapes("Table").Table.Cell(1, i).Shape.TextFrame.TextRange.Text
Next

Dim tmpString As String
For i = 1 To 10
    tmpString = tmpString & "," & Box(i)
Next

tmpString = Mid(tmpString, 2)
Debug.Print tmpString

Stop

End Sub

実行すると,イミディエイトウィンドウに  a,b,c,d,e,f,g,h,i,j が出力されます。Stopで止めているのはローカルウィンドウを見るため。
f:id:chemiphys:20170109161633p:plain

どのように変数が入っているかわかると思います。
いろいろ説明が必要なので,書いていきます。
Dim Box(1 To 10) As String
   →Box(1)~Box(10)という変数を文字列型で宣言しています。
Dim i As Long
   →iをLongという長整数型で宣言しています。IntegerやByteあたりでもいいです。オーバーヘッドの話を見てからわたしは整数はLongしか使いません。好みです。

次が主題のループ iの値を1から10まで変化させて繰り返すという意味です。

For i = 1 To 10
    Box(i) = ActivePresentation.Slides(1).Shapes("Table").Table.Cell(1, i).Shape.TextFrame.TextRange.Text
Next

同じ意味のものをループを使わず書いたら,

    Box(1) = ActivePresentation.Slides(1).Shapes("Table").Table.Cell(1, 1).Shape.TextFrame.TextRange.Text
    Box(2) = ActivePresentation.Slides(1).Shapes("Table").Table.Cell(1, 2).Shape.TextFrame.TextRange.Text
    Box(3) = ActivePresentation.Slides(1).Shapes("Table").Table.Cell(1, 3).Shape.TextFrame.TextRange.Text
    Box(4) = ActivePresentation.Slides(1).Shapes("Table").Table.Cell(1, 4).Shape.TextFrame.TextRange.Text
    Box(5) = ActivePresentation.Slides(1).Shapes("Table").Table.Cell(1, 5).Shape.TextFrame.TextRange.Text
    Box(6) = ActivePresentation.Slides(1).Shapes("Table").Table.Cell(1, 6).Shape.TextFrame.TextRange.Text
    Box(7) = ActivePresentation.Slides(1).Shapes("Table").Table.Cell(1, 7).Shape.TextFrame.TextRange.Text
    Box(8) = ActivePresentation.Slides(1).Shapes("Table").Table.Cell(1, 8).Shape.TextFrame.TextRange.Text
    Box(9) = ActivePresentation.Slides(1).Shapes("Table").Table.Cell(1, 9).Shape.TextFrame.TextRange.Text
    Box(10) = ActivePresentation.Slides(1).Shapes("Table").Table.Cell(1, 10).Shape.TextFrame.TextRange.Text

こうなります。大変ですよね。わざと書くのが大変なものを選んでループの有効性を強調したわけですが,ループの便利さは伝わると思います。
特に,どこか間違えたとき書き直すことを想像してみてください・・・(;´▽`A``

その後,tmpStringという変数に , をいれつつBox(1)~Box(10)の中身をつなげていくループを書いています。

ここまでの結果は実は tmpStringには ,a,b,c,d,e,f,g,h,i,j が入ります。最初の , が非常に格好悪い。
ループ部分をシンプルに書こうとすると,一番最初や一番最後に余分にくっつくことはよくあるので,こういう時に文字列を扱う関数 left関数 , mid関数 , right関数 そして文字数を扱う Len関数 がとても便利。
このあたりを使いだすととても面白くなってきます。。(゚▽゚*)
Mid(tmpString,2)というのは tmpStringの2文字目からを切り出しますよ,という意味です。

基本的にはループっていうのはこんな感じのものです。

素数が決まっている,変数の変化が決まっているときはForループがいいかな。
For i=10 to 1 Step -1
このように, Stepを使うと変数の増分を決めることができます。2ずつ増やしていくとかいくらかずつ減らしていくという書き方も可能。

②Do ~ Loop
最初は苦手だったループですが,最近はよくお世話になります。
無限ループをさせてアニメーションとかする時はこれがベスト(゚▽゚*)無限ループは本当はだめなやつです。ループを抜け出す書き方がきちんとできるようになってから扱いましょう。
VBAはDoEventsというのを適切に挟んでおけば,Ctrl+Pauseで止めれます。
逆に言えばその辺をちゃんとしていなかったら帰ってきません。強制終了でそれまでの作業にサヨナラすることも多々。
重々気を付けてくださいね・・。

さて,例です。

Sub test4()
Dim Box(1 To 10) As String
Dim tmpString As String
Dim i As Long

i = 1
Do
    Box(i) = ActivePresentation.Slides(1).Shapes("Table").Table.Cell(1, i).Shape.TextFrame.TextRange.Text
    tmpString = tmpString & "," & Box(i)
    If Box(i) = "h" Then Exit Do
    i = i + 1
Loop

Debug.Print Mid(tmpString, 2)
End Sub

すこーし先ほどとコードも変わってます。
さっきはわかり易さを重視して二段階にループをわけていましたが,今回は一度に処理していきます。

For Nextとの違いは勝手に数値が変化していってくれないことです。
Doの直前で i=1 と指定し, Loopの手前で i=i+1 と1ずつ増えるように書いています。
大事なのがDo Loopを抜ける条件

    If Box(i) = "h" Then Exit Do

Box(i)の中身が"h"ならループを抜けるという書き方です。これがポイント。
Do Until , Do While , Loop Until ,Loop while など最初や最後に抜ける条件を書くこともできますが,すこし難しい。
想定外の動きをすることもありますので,わたしは Exit Do で好きなタイミングで抜ける書き方をします。

柔軟にループをまわせるという意味ではとてもいいループです。

③For Eachループ
本当はコレクションの話とかしなきゃいけなくなるけど,そんな話を始めると途方もないのでシンプルにいきます。

f:id:chemiphys:20170109170100p:plain
表を含めて4つの図形を置いています。

Sub test5()

Dim TSlide As Slide: Set TSlide = ActivePresentation.Slides(1)
Dim s As Shape

For Each s In TSlide.Shapes
    Debug.Print s.Name
    Debug.Print s.Left
    Debug.Print s.Top
Next
End Sub

For Each 要素を表す変数 in 要素のコレクションを表す変数

こんな感じで書きます。
今回の場合は 要素を表す変数は s としています。 Shape と宣言しています。
要素のコレクションは スライド1のShapesのように複数形になっていることに注目してください。
オブジェクト等の理解が必要なループですが,とても便利です。

上の例を実行すると

Table
 282.1818 
 21.03032 
Isosceles Triangle 4
 168.7273 
 37.97276 
Rectangle 5
 255.2727 
 141.0909 
Right Arrow 6
 395.6364 
 148.7273 

このようにイミディエイトウィンドウに返します。
図形の名前,Leftプロパティ,Topプロパティを書き出してくれていますし,要素数を調べなくてもすべての要素に適用してくれる。

とてもかっこいいループです。(個人の見解です)

ちょっと難しい面もありますが,使えると楽しい。おすすめします。

もう基本として書くことはしませんが,変数の宣言をきちんとしはじめると,逆に立ちはだかる壁が出てきます。

変換関数CLng 関数が便利なので,メモだけ最後にして,基本シリーズ終わります。

長整数型に変換・・CLng() ,文字列型に変換・・ CStr(),整数型に変換・・ CInt()