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

Powerpoint VBAを使おう!

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

原子の構造 コードの記録 Powerpoint VBA

Powerpoint VBA

chemiphys.hateblo.jp

当たり前のように,最近は標準モジュールとクラスモジュールをぺたぺた貼ってますが,そのあたりに触れることもあまりないのでそのあたりから。

f:id:chemiphys:20170216202455p:plain

ExcelVBAだと,Sheet1とかSheet2とか各オブジェクトのモジュールと,標準モジュールと,クラスモジュールとフォーム関連では書く場所が異なります。

Powerpointになると,オブジェクトは最初隠されているので,最初はすっからかんです。

そこで,最初にすることは,コードを書く場所の確保。

 挿入 → 標準モジュール で標準モジュールを書く場所ができます。パワーポイントVBAのメインの仕事場です。

 さらに,

 挿入 → クラスモジュール でクラスモジュールを書く場所を作ります。

標準モジュールでは,あまりモジュールの名前は重要にならないことが多いのでModule1のままでよいですが,クラスモジュールはその名前がとても大切です。

今回の私のコードではPlateObject.cls と書いていますので, その PlateObject というのをクラスモジュールの名前にします。

f:id:chemiphys:20170216203104p:plain

矢印の場所が,クラスモジュールの名前になる場所です。ここは編集可能ですので,PlateObjectと書き換えます。自分でクラスモジュールを作るときは,好きな名前をつけますが,名前大事です。

ここまで準備できたら,標準モジュールのほうに,前の記事の標準モジュールの中身を貼り付ける。

PlateObjectのクラスモジュールの中身をクラスモジュールのほうに貼ります。

これで準備完成ですので,あとは Powerpointのほうにもどって,

 開発→ マクロ → Start というマクロを実行。 開発タブが無い方は 表示 の右端にもマクロがいますのでそちらで動きます。

私の動作環境は2016です。たぶん2013は問題なく動くと思いますが,2010付近からはなんとも言えないのが正直なところです。


さて,コードのほうです。目新しいことはとくにはしていませんが,今回けっこう便利だったのは,値リストをConstで,区切りでString型で宣言しておいて,Splitで取り出すのはけっこう便利でした。

Const arr原子大きさ = "1,4.67,5.07,3.70,2.70,2.57,2.47,2.47,2.40,5.13,6.20,5.33,4.77,3.90,3.67,3.47,3.30,6.27,7.70,6.57"
Const arr質量数 = "1,4,7,9,11,12,14,16,19,20,23,24,27,28,31,32,35,40,39,40"
Const arr元素記号 = "H,He,Li,Be,B,C,N,O,F,Ne,Na,Mg,Al,Si,P,S,Cl,Ar,K,Ca"

このあたりです。20元素分のデータをそれぞれ格納するんですが,配列等をそれぞれに用意すると変数だらけで,私のような無計画な人にはつらい。
これを

 .TextFrame.TextRange = i & Split(arr元素記号, ",")(i - 1)

ここなんかで使ってますが, Split関数で要素を取り出すということをしています。インデックスの初期値は0です。基本私はループの際 i=1スタートなので,-1をして調整しています。

変数を増やしすぎない工夫として,Withを使うことで変数にしなくても一気にいろいろなプロパティを設定できる,という方法にやっと最近慣れてきました。

    With TargetSlide.Shapes.AddTextbox(msoTextOrientationHorizontal, 600, 420, 170, 50)
        .TextFrame.TextRange.Text = "STOP"
        .ActionSettings(ppMouseClick).Action = ppActionRunMacro
        .ActionSettings(ppMouseClick).Run = "StopMacro"
        .Fill.ForeColor.RGB = vbRed
        .Name = "0"
    End With

こんな書き方です。Withを使わない場合は,ちょっと書きづらいので,変数を使いがちですが,Withだとらくちん。Excelの記録マクロがよくこんな書き方をしますよね。
また,上のコードはボタンを作って,それにマクロを関連付けている部分ですので,けっこう便利な方法だと思います。

Sub Make(図形 As Shape)
    Set TargetSlide = ActivePresentation.Slides(1)

Subプロシージャの引数に図形を取らせるように書いて,それを図形のクリック時に実行とかさせると,マクロのトリガーになった図形を引数として使えるマクロが書けます。
今回は各ボタンに原子番号の名前を付けていて,その番号で動作を分岐させています。この仕組みは個人的にはとても便利だと思っています。
日本のVBAのページではこのことに関する記述はあまり見ませんでした。見つけたときは衝撃を受けたものです。

Dim Plate(1 To 4) As PlateObject

Plateという配列変数をPlateObjectとして宣言しています。
このように,クラスモジュールはその名前がオブジェクト名になりますので,とっても大事です。

 原子番号 = CLng(図形.Name)

文字列に値を格納させることが多い私にとって,変換関数はとても大事。
CLngというのは, Long型にしますよ,という関数です。図形の名前はString型なので,変換して上げないと,うまくいかないケースが多々。
"1"はどうみても1だと人にはわかりますが,きちんと変換して上げないと怒る関数等たくさんいますので,変換関数を知ると幅が広がると思います。

 For i = Switch(原子番号 < 3, 1, 原子番号 < 11, 2, 原子番号 < 19, 3, 原子番号 > 18, 4) To 1 Step -1

わたしはちっちゃいころBASICを見て育ちました。なので,:でたくさん繋いだりしたプログラムをよく目にしていたほうです。
縦にながーく書くより,適度に横にも広がるコードのほうが好みなので,このSwitch関数もよく使います。
どうも思い通りに動かない時もあり,手を焼くこともありますが,一行で縦に長いif文と同じような条件分岐を書ける関数です。

     DoEvents
        Sleep 50
        If StopFlag = True Then Exit Do
        
    Loop
End Sub

Sub StopMacro()
    StopFlag = True
End Sub

抜け出す条件が書かれていない Do Loop を私はけっこうよく書きますが,
その中にDoEventsと適度なSleepと StopFlagのようなboolean型を準備しておいて,
ボタンを押せばループを抜け出す,という書き方をよく私は使います。好きな書き方ですが,

きちんとこれらをそろえないと,強制終了しか止める方法がなくなることがありますので,試される場合はご注意ください。

        Set 粒子(i) = TargetSlide.Shapes.AddShape(msoShapeOval, StartX + dX, StartY + dY, 15, 15)
        粒子(i).Fill.ForeColor.RGB = vbCyan
        粒子(i).ThreeD.BevelBottomDepth = 7.5
        粒子(i).ThreeD.BevelBottomInset = 7.5
        粒子(i).ThreeD.BevelTopDepth = 7.5
        粒子(i).ThreeD.BevelTopInset = 7.5
        粒子(i).Line.Visible = msoFalse

粒子を立体的に書いているところです。
円の縦,横の大きさの半分の数値を 3D関連の値に入れると球っぽく描いてくれます。
マクロを使わなくてもいけますので,便利と思います。
ダイアログではpt単位で入力するようになってますが例えば円の縦・横が3cmならダイアログに 1.5cmとか入れるとちゃんとptに書き換えてくれます。
好んで使います。

わたしのクセに近いコードはこのあたりまでかな。あとは特別なことはしていないと思います。

癖の強いコードを書きますので,読みづらいかもしれませんが,動いたのでいいんです(゚▽゚*)

ここまで来たら,実際説明とかで使えそうかなーと思ってます。

人によってこだわる場所は違うわけですし,表現方法ももちろん違う,色の好みとかもそうです。

私にとっての原子のモデル化はこんな感じでしたという例でした。。