熱運動クラスモジュール化②速度実装の前に課題解決
①はこちら
chemiphys.hateblo.jp
ほんとにありがたい方々にアドバイスもらえています。他をどうこうする前にやらなきゃいけないことだったので,
たぶん解決できた気がするので,書きます。
imihitoさんのご指摘
Boxクラス内で使っているIsEmpty関数はVariant型専用関数なので、今回の場合だと意図した通りに動かないと思います。
対処として、判定方法を変えるのも手ですが、Drawメソッドの引数に渡すのはどうでしょうか?
わたしもここがごちゃごちゃしててだめだなぁと思ってて,どうしていいかわからなかったところ。
標準モジュール Dim B1 As Box Set B1 = New Box B1.pLeft = 80: B1.pTop = 100: B1.pRight = 150: B1.pBottom = 250 Set B1.pSlide = TSlide B1.Draw B1.AddMolecile 5 Box.cls冒頭 Public Sub Draw() If IsEmpty(pSlide) Or IsEmpty(pTop) Or IsEmpty(pBottom) Or IsEmpty(pLeft) Or IsEmpty(pRight) Then Exit Sub Dim Box As Shape
たぶん改善できました。
標準モジュール Sub test() Dim TSlide As Slide: Set TSlide = ActivePresentation.Slides(1) Dim B1 As Box Set B1 = New Box B1.Draw TSlide, 100, 250, 80, 150 B1.AddMolecile 5 Stop End Sub Box.cls冒頭 Public Sub Draw(objSlide As Slide, lngTop As Long, lngBottom As Long, lngLeft As Long, lngRight As Long) Set pSlide = objSlide pTop = lngTop pBottom = lngBottom pLeft = lngLeft pRight = lngRight Dim Box As Shape
引数が足りなければ勝手に怒ってくれますので,判定しなくてもよくなりました。
thomさんからのご指摘
あとで操作するには、シェイプもクラスに保持させると良いです。プロシージャ内のローカル変数だとプロシージャ実行後に消えてしまいますので。
具体的にはMoleculeクラスにShape型のインスタンス変数を持たせてシェイプを保持させます。
また、BoxクラスにCollection型のインスタンス変数(モジュールレベル変数)を持たせて複数のMoleculeを保持します。ややこしい用語を使ってしまいました。
Dim shpEn As ShapeをAdd命令から外に出すという意味です。ついでにPublicにすると内部からも外部からもアクセスできて、Moleculeが生存している間はずっとシェイプを保持してくれます。
スコープのことは難しいですが,クラスモジュールと標準モジュールでやりとりしていくにはどうしてもきちんとしないといけないところ。この辺が弱くて今までやれてなかったわけで,乗り越えるべきところです。
Molcule.cls冒頭 shpEnをパブリックに出しました。Boxモジュールからは見える Public shpEn As Shape Public pSpeed As Long Public Sub Add(半径 As Long) Set shpEn = pSlide.Shapes.AddShape(msoShapeOval, mLeft + 半径 + (mRight - mLeft - 2 * 半径) * Rnd(), mTop + 半径 + (mBottom - mTop - 2 * 半径) * Rnd(), 半径, 半径) Box.cls冒頭 非固定長配列をどうやってPublicで宣言するの!?と少し悩んでいて, もう一度thomさんのアドバイスを見てあぁ,配列はCollectionに放り込むのかと解釈。 Public pSpeed As Long Public Molecules As Collection 'ここでコレクションを利用 Public Sub AddMolecile(粒数 As Long) Dim e() As Molecule ReDim e(粒数) Dim i As Long Set Molecules = New Collection For i = 1 To 粒数 Set e(i) = New Molecule e(i).mLeft = pLeft e(i).mTop = pTop e(i).mRight = pRight e(i).mBottom = pBottom Set e(i).pSlide = pSlide e(i).Add 15 Molecules.Add e(i) Next End Sub
ローカルウィンドウを見てみた
B1というBoxがあって,その中にコレクションMolculesがあってその中に各粒のプロパティがある。
アクセスの仕方は
Dim en1 As Molecule Set en1 = B1.Molecules(1) Debug.Print en1.mTop
For eachが使いやすい場面ですね。今はとりあえず一つの粒にアクセスしてみていますが,
ちゃんとプロパティに到達できる。
多数のフィールドを持つデータと格闘したときに,ソートキーを与えたくていろいろ試した経験が生きた。あれやってなかったらアドバイスの意味がつかめていない(;´▽`A``
コレクションの存在意義もすごいですね。可変長配列をぽんと上位モジュールにわたせるのかスゴイナ。
なんとか課題の解決はできたので,先に進めそう。
今はPublicでプロパティを扱ってるけど カプセル化するとき ユーザー定義型のをどう返すんだろうとか,こんどはまた次の?が出てきました。
x,y座標はいっぺんに計算したほうが楽ですし。でも,今は無視して進もう・・(ΦωΦ)今の敵はそいつじゃない。。