アットウィキロゴ

4種の命令とプロシージャ

4種の命令とプロシージャ


まだ作成予定しかないけど、方針だけメモ

方針

以下の違いと使われ方について調査、メモする。
  • プロパティ
  • メソッド
  • ステートメント
  • 関数
  • プロシージャ






まとめ


とりあえず国語と絡めるとわかるかも?
  • プロパティ
"主語"、"目的格"、"この語の後には数詞が続く"などの分類・性質。

  • メソッド
"動く"、"走る"、"描く"などの動きを表す単語、要するに動詞や述語。

  • ステートメント
"てにをは"や、"To be Continued"などの助詞や定型句。

  • 関数
"~だろう"、"~ない"、"~したい"など、付加することで同一のニュアンスを付加する助動詞。

  • プロシージャ
"いつもお世話になっております。"などの定型文や、メールの署名などのテンプレート。

……うん、むしろ難しくなったかな。
ちなみに、上記例で当てはめるなら、『変数』は代名詞、『定数』は名詞、あたりに相当するだろうか。
マクロではステートメントは記録されない(≒"てにをは"は存在しなくても意味は通じる)という意味では実言語に似てる気がする。



プロパティ

とりあえず参考サイト


プロパティとはなんじゃらほい

プロパティというのは、あるオブジェクトにおける性質だとか特質、属性、特性といったものをひとくくりにした概念である。
よって、プロパティを変更すれば、そのオブジェクトの特性は変化する事となり、見た目や取り扱われ方に変化が生じる事となる。
ただ、こいつが曲者で、一つのオブジェクトが持つプロパティはすさまじく多い、そのうえ、すべてのオブジェクトが同じプロパティを持っているわけでもない。
マウスとキーボードを使う感覚で、VBAで同じ操作をしようとしてもうまくいかないのは大抵どこを変更したらいいかよくわからないという部分に由来している。

例えば、".Collor"というプロパティがある。
このプロパティはシェイプなどの背景色情報を格納していて、そのプロパティに色情報を代入する事でシェイプを指定した色で塗りつぶしたりできるわけだ。
単純に考えて、そういうプロパティなんだってわかってしまえば、あとは色を変えたい対象を指定して、その末尾に".Collor"つけて色指定すればいいだけだし、色変えるの簡単じゃーん!

――とか思うわけだが、実際にはそううまくいかない。
例えば".Charactor.Text"プロパティはシェイプに記述されたテキストを示すが、これを".Charactor.Text.Collor"と記述したところでテキストの文字色は変えられない。
テキストの色を変えるには".CharProps"プロパティに文字色を表す定数を指定し、そこに色情報を代入するという手順を踏まないといけないし、コネクタの色を変えるには".CellsSRC"プロパティに色を定義しているSection, 行, セルの定数を指定してその値に色情報を代入するという方法を取らなければならない。
※ちなみに".CellsSRC"を使ってテキストの色を変える事もできるようだ。

確かにユーザーがマウスを使って色を変えようとするとき、シェイプ、テキスト、コネクタ(線)それぞれ押すボタン(使用するパレット)が違うので、内部処理的には全く別の行為だというのは否定のしようもないのだが、文字列側から見れば『色を付ける』という意味的集合において同一であると認識するのが自然だ。
それらを別種の処理だとプログラマが認識するためには、あらかじめプロパティについて一定の知識を持っている事が求められる。


シェイプシートとセル

シェイプシートとは各シェイプごとにプロパティ値を一覧できるExcelシートのようなものだ。
対象のオブジェクトを選択した状態で、上部メニューの『ウインドウ>シェイプシートの表示』と選択することで表示される。
※ツール>オプション>詳細設定タブ>開発モードにチェックを入れる事で右クリックメニューに『シェイプシートの表示』が表示されるようになる。
そして、どうやらこのシェイプシートの値はすべてVBAから操作することができるらしい。
シェイプの位置からフォントの色まで、値を手動で変えてみればわかるが、このシェイプシートを操作することでできる事は多い。


" .CellsSRC"プロパティの怪

前述した".CellsSRC"プロパティというのは引数に指定した値で参照先プロパティが変わるらしく、以下のように記述する事で、プロパティの集合領域の中から一つを選択して参照することができるらしい。
~.CellsSRC(セクション, 行, セル)

そのプロパティの定義はセクション、行、セルという形態で指定できることから、Excelシートのような場所に定義されていると想像できるわけだが、ここで思い出すものがある。
シェイプシートだ。

シェイプシートを見ればわかるが、Excelでセクションごとに分けられた各セルに位置情報やフォントサイズが格納されており、これはまさしく" .CellsSRC"プロパティの参照先なのではないか!?と思ってしまうわけだが、そうは問屋が卸さないのである。
次のコードを見てほしい。
.CellsSRC(visSectionObject, visRowLine, visLineColor)

これはオブジェクトの線の色を定義している領域にアクセスする際の指定子である。
ではオブジェクトのシェイプシートを見てみよう。

いかがだろうか、セル名はなんとかわかるが、セクション名と行名がイマイチかみ合わないのがわかるだろうか。
これのおかげで、すんなりと目的のプロパティをいじくれないストレスがすごい。

ただ、プログラミング言語というものには、往々にして設計者の哲学やらポリシーがあるもので、それが理解できるくらいに習熟すると、ある日、ストレス源としか思えないような無駄と思われた構造に一つの規則性が見えてスッキリしたり、設計者のセンスに感動したりもする。
もちろん、中にはそんな事関係なく、旧バージョンに新しい機能上乗せ、上乗せしてるうちにカオスになったりしてる場合もあるので、あまり期待してもしょうがないが、新しい言語を学ぶ側としては、哲学やポリシーの存在は習得における重要な道しるべとなりうるのでVBAがそのような言語であることを祈るばかりだ。

ともかく、我々はそれがどんなクソであろうとも" .CellsSRC"プロパティを使いこなす必要があることは事実だ。
各プロパティについては基本的にあまり触れる予定はないのだが、紹介した手前、参考程度に紹介しておく。
以下は先に紹介した" .CellsSRC"プロパティの書式だが、
~.CellsSRC(セクション, 行, セル)

()の中にある"セクション"、"行"、"セル"が取りうる値は定数としてあらかじめ決められており、その定数により、どのプロパティを操作するかを表現できる。
取りうる定数の一覧はMSがリファレンスとして公開しているので、そちらを参照してほしい。

◆セクション
VisSectionIndices の定数



このほかにもプロパティには様々なものがある。
それぞれに使い道と使い方があるので、やりたいことを実現するのに必要なプロパティだけでも覚えておきたい。
本項目の最初に紹介した参考サイトにプロパティのリファレンスがあるので、マクロで使用感をつかみつつ使い道を探りたい。



メソッド

とりあえず参考サイト


メソッドたぁなんぞや

メソッドというのは、コンピューターに対するいくつかの命令によって定義される一群の処理を、意味的にも単語数的にも一つの"命令"として扱うための仕組みがあり、その仕組みによって作られた"命令"のうち、あらかじめソフトウェア側で用意されたもの……といったところでしょうか。
ごちゃごちゃ書きましたが、要はオブジェクトに動作指示をするためのコマンドです。
動かしたいなら".Move"ですし、追加したいなら".Add"です。

なんでそんなごちゃごちゃ書いたかと言えば、MoveやAddという単語が人間にもたらすイメージは1つに収束しますが、コンピューターの視点から見れば、Moveするにもいくつもの命令を処理しなければならないという人間とコンピューターの違いを踏まえる必要があるからです。
これはあとで解説する"プロシージャ"の理解において重要な事柄なので、あなたがマウスで動かす単純な操作もコンピューターから見れば複雑な行為なのだという事だけは理解しておいてください。

プロパティと同じく、こいつも階層構造の中に格納されていて、やはりオブジェクトごとに使用できる種類が違う。そして、すごいたくさんあるという点も同じだ。


メソッドの利用・記述方法

メソッドはプロパティと同じく階層構造の中に収容されているわけですが、同時に"プロシージャ"であり"サブルーチン"でもあることから"Call"ステートメントによって呼び出す方法も使用できてしまう、というより"Call"ステートメントで呼び出す方が明示的で良いっぽい。。。
何を言っているかわからないかもしれないが、私もわからなかった。

情報精度の検証はすべてが終わってからするとして、ざっくりと説明すると、"メソッド"、"プロシージャ"、"サブルーチン"というのは何を基準としてソレを表現するか、という点で呼び名が変わっているに過ぎない。例えるなら"室内猫"、"ネコ科"、"お隣の猫"という違い程度のものだ。それぞれは同じ"猫"に対する呼称だが、視点ごとにソレをより的確に表現する相対的な呼称があるというだけの話だ。

とはいえ、横文字なおかげで非常にわかりにくい。本当にわかりにくい。無駄にわかりにくい。
"基本命令"、"命令集合"、"補処理"とか、
"既定処理群"、"独立処理群"、"外部処理群"とか……これはこれで分かりにくいな。。。
あきらめて違いがわかるまで関連サイトを読み込むことをオススメします。

さて、以下はまったく同じ動きをするコードですが、上2つはメソッドを直接利用。3つ目はFunctionプロシージャ側でメソッドを利用して、関数的に呼び出す形での記述(自分の練習用なので非推奨)となります。
◆マクロで記録
Sub Macro4a()

    ActiveWindow.DeselectAll
    ActiveWindow.Select Application.ActiveWindow.Page.Shapes.ItemFromID(10), visSelect
    Application.ActiveWindow.Selection.Move 0.03937, -1.948819

End Sub

◆Callステートメントで書き換え
Sub Macro4b()

    ActiveWindow.DeselectAll
    ActiveWindow.Select Application.ActiveWindow.Page.Shapes.ItemFromID(10), visSelect
    Call Application.ActiveWindow.Selection.Move(0.03937, -1.948819)

End Sub

◆オマケ(Functionの練習)
※変数型はObjectでも動くし、Variant型ならSetステートメントもいらない。
Sub Macro4c()

    Dim objSelection As Selection
    
    ActiveWindow.DeselectAll
    ActiveWindow.Select Application.ActiveWindow.Page.Shapes.ItemFromID(10), visSelect
    Set objSelection = test(0.03937, -1.948819)
End Sub
    
Function test(x As Integer, y As Integer) As Selection

    Application.ActiveWindow.Selection.Move x, y
    Set test = Application.ActiveWindow.Selection
    
End Function

なんか他にもある気がしてきた。
とまあ、この違いのおかげで、あれ?これはメソッド?ならこっちの書き方でイケる?あれ駄目か?じゃあプロパティか?違った関数か……みたいな迷路に迷い込むわけです。
なお、この違いこそが、Visio VBA基礎知識の『要素だけでなく動作も階層の中に』項目で登場する".Move"に関わるお話の調査結果……という事になります。



以下調査中



ステートメント

とりあえず参考サイト



ステートメントぉ?

声明だとか、発表、陳述、などと訳される言葉だが、プログラミングにおけるこのステートメントに対する個人的なイメージとしては『機械の言葉と人間の言葉を分かつ境界線』といった所だろうか。
実際、ExcelやらVisioの"マクロの記録"による記述ではこのステートメントは登場しない(※1)。

例えばある操作を5回繰り返す事を考えたとき、"マクロの記録"では単純に同じ操作を5回記述するのが関の山だが、人間はこのステートメントを駆使する事で反復処理という高次な処理に昇華することができる……といった具合だ。
これは、ユーザーの判断の結果としての一連(一続き)の操作を記録する"マクロの記録"と、ユーザーの判断の一部もプログラムに任せてしまおうという"プログラミング"の違いに由来している。

例えば、シェイプが"Decision"だったら赤色に、"Process"だったら青色に塗る事を考えたとき、"マクロの記録"ではそこにあるシェイプが"Decision"であることを判断するのは人間だが、"プログラミング"ではコンピューターに任される。
さらに言えば"マクロの記録"ではそれが"Decision"だったら、とか"Process"だったらとかいう判断も存在しない。単に"ユーザーが選択したID:XXのシェイプ"の色を変えるだけだ。そのためそのIDを持つシェイプを削除してしまえば、もうこのマクロはただのゴミになってしまう。

プログラミングではそうした応用力の無いマクロに応用力を持たせ、人間らしい判断を伴う動作を実現するにあたり、"ステートメント"が重要な役割を占めている。。。と私は感じる(笑)。
ちなみに、上記の動作を実現する際、プログラミングで使われるステートメントはたぶん"If...(Then...)Else"とか、"Select Case"とかだろう。

※1
調べたら"Sub"とか"End"もステートメントなので、厳密には登場する。
が、それは例外というやつなので基本的には登場しない認識でOK。


ステートメントはどこにある?

プロパティにしろメソッドにしろ、階層構造の中にある(階層構造で記述する必要がある)と解説したが、ステートメントもやはり階層構造の中にあるのだろうか?
答えは否だ。
究極的には"プログラミングの仕様"の中という事になるが、先のプロパティやメソッドに関する説明(階層構造の中~云々)と同じ次元で説明すれば、ステートメントはプログラミング上ではそれ単体で存在する独立した存在だ。
それ単体で存在し、他の要素に方向性を示す。。。という感じか。
信号機とか、標識みたいなものだと思っておけばよい。


基本的なステートメント

こればっかりはマクロに頼るわけにいかないし、作るたびにリファレンスを引く……というのも効率が悪い。
よく使うのだけでも覚えろ!
No. ステートメント 役割
01 Sub Subroutineの頭文字。じゃあMainroutine用のステートメントがあるかと言えば無い模様。
02 End Sub Subプロシージャのおしまいを示す。
03 Dim 変数を宣言するお約束。これの使い方くらいは自分で調べて。
04 Set Object型変数に値を代入する時は他の非Object型変数で"="を使って値を代入するのに加えて行頭にこのステートメントが必要になる。
05 Call 呼んで字のごとく、何かを呼び出すためのステートメント。その"何か"はいわゆるサブルーチンだとか、メソッドだとかが属するプロシージャである。具体的には自分以外の"Sub"プロシージャとか、"Function"プロシージャ、あとはメソッドなんかがコレによって呼び出される。
06 If Then 条件分岐の王様。プログラミングやってれば最初に覚えて最初に理解できて、最も汎用性にあふれるステートメントの優等生。
07 For Next 明示的に回数を指定して反復処理させるときはコレ。
08 For Each 次の項で説明してるのでそちらを参照。

ステートメントの使い方

For Eachステートメント
以下はFor Eachステートメントのテストプロシージャ。
選択したシェイプのテキストを選択した順番に結合してメッセージボックスに表示する。
ここまで勉強した内容でパパっと書いてみたら奇跡的に一発で動いて感動したので掲載。
Sub ForEachTest()
    
    Dim objText As String
    Dim objMember As Object
    
    For Each objMember In Application.ActiveWindow.Selection
        objText = objText + objMember.Characters.Text
    Next objMember
    MsgBox objText
    
End Sub

要するに"For Each"の後の変数"objMember"は"In"の後ろに来る複数のオブジェクトグループに属する個別のオブジェクトを格納するためにあります。
    For Each 単体オブジェクト In 複数オブジェクト
        単体オブジェクトに対する処理内容
    Next 単体オブジェクト
という感じ。

処理対象は"In"の後ろに来るグループに含まれるオブジェクトの一つ(メンバー)で、最初の処理対象となるメンバーはどうやら最初に選択したオブジェクトになる模様。
以下の画像ではシェイプ内のテキスト順に選択してみました。

ちなみに、マウスを使って一個一個選択するのではなく、ドラッグ操作による範囲指定で複数シェイプの一括選択を行った時はよくわからない。ある状況では常に右下がアクティブシェイプになるし、ある状況では常に右上がそうなる。内部処理的にはルールがあるのだろうが、そこまで調べる必要性が見いだせないので、ここではこれ以上追及はしない。
ちなみにちなみに、Excelの場合は"Range"範囲内のアクティブセルが最初の処理対象になるんじゃないかなぁと思っているのだが、いずれExcel VBAのWikiを作る時に検証しよう。

閑話休題。

最初のメンバーに対する処理が完了したら、"Next"ステートメントによって順次メンバーを切り替えていくのだが、ここで難しいのはその処理の部分だろうか。
        objText = objText + objMember.Characters.Text

"objMember"は"Application.ActiveWindow.Selection"に属する1オブジェクトを順次格納していくため、使用できるプロパティやメソッドは"Application.ActiveWindow.Selection"で使用できるものとは異なる(たぶん)。

WEB上の他のVBA解説サイトではExcelの"Range(セルの選択範囲)"オブジェクトをベースに紹介しているので、Visioでは使えないのかなぁと思ったが、"Selection"オブジェクトも複数オブジェクトだなぁと思って試したらうまい事動いたので、かなりうれしかった。
そもそも需要が少ないのが原因だろうが、VisioでFor Eachを使用するコード例を示して解説しているサイトはあんまりないので何かの役に立てば幸いだ。
ともかく、For Eachステートメントは複数のオブジェクトに同じ処理を順次実行する場合に使用できるという事のようだ。


関数

とりあえず参考サイト



関数ってあの関数?

Excelをやってる人なら、当然、『あの関数?』と思うかもしれませんが、"一緒だと思っていると失敗します"。
例えば"Trim"関数とか、使い方はExcelの"TRIM"関数と全く同じなのですが、結果が違う!

以下のような文字列があったとします。
"    1 2  3   4    5     "

これをExcelの"TRIM"関数を通すと、、、

となります。
一方、VBの"Trim"関数を通す場合、
Sub TrimTest()
    Dim TrimTest As String
        TrimTest = "    1 2  3   4    5     "
    MsgBox "原文 : 「" + TrimTest + "」" + vbNewLine + "結果 : 「" + Trim(TrimTest) + "」"
End Sub

という感じで使用して、結果は以下の通り。

まとめるとこう。
Excel TRIM : "1 2 3 4 5"
VB Trim     : "1 2  3   4    5"

要するに、Excelの"TRIM"関数は
  1. 前後のスペース削除
  2. 文字間のスペースは1個になるように調節
という二つの事をしているのですが、VBの"Trim"関数は
  1. 前後のスペース削除
しかしていないという事です。
他の関数も一緒だったり違ってたりしてるのでしょうが、個別に調べるのはダルいので各自必要な関数について使い方をお勉強すればよいと思います。

とはいえ、それ以外はExcelの関数と通じる部分が多いのも事実、プロパティやメソッド、ステートメントに比べればよほどとっつきやすいのではないでしょうか。

というわけで、あとはリファレンス作ってるサイトに任せた。


関数もプロシージャ?

関数もプロシージャでしょうね。
ユーザーが作成できる関数として"Function"プロシージャがありますが、"Function"プロシージャを"関数"と呼ぶ事もあるそうなので、逆説的に"関数"もプロシージャでしょう。
ここらあたりの違いについては次のセクション『プロシージャ』で解説します。


プロシージャ

結局プロシージャってなんなのさ?

一般にプログラミング界隈(?)では"手続き"と訳されるそうですが。
"複数の処理によって構成される意味的に単一な命令群"といったところでしょうか。
ただ、"意味的に単一"であることは理想であって、"プロシージャ"の定義において必須ではないというのは断っておきます。

身近な例でプロシージャに近いものというと、何かなぁ、全自動洗濯機とかかなぁ。。。
  1. 洗い桶に洗濯物を入れる
  2. 洗い桶に水を入れる
  3. 石鹸を投入する
  4. 洗濯物を攪拌・揉み混ぜる
  5. 洗い桶の水を捨てる
  6. 洗い桶に水を入れる
  7. 洗濯物を攪拌・揉み混ぜる(すすぎ)
  8. 洗い桶の水を捨てる
  9. ~略~
  10. 洗濯物を絞る(脱水)

という洗濯における各処理を
  1. 全自動洗濯機に洗濯物を入れる
  2. ボタンを押す

と短縮できるのは"全自動洗濯機"というプロシージャが洗濯の各工程を"洗濯機に掛ける"という1つの処理(行為)にまとめてくれているからです。
尚、全自動洗濯機の例では"汚れた洗濯物"を渡して"洗いあがった洗濯物"を返すので、"関数"的なプロシージャという事になりそうです。引数と戻り値の話は次の次あたりの項で解説します。

さて、実際にプロシージャをどういうシチュエーションで使うかと言えば、"よく使うけど、デフォルトで用意されていない処理"を自前で作成する時に使います。この時、デフォルトで用意されている"プロシージャ"の事を"メソッド"とか"関数"、ユーザーが自前で作成した"プロシージャ"を"Sub"プロシージャとか"Function"プロシージャと呼ぶわけです。

プロシージャを作るにあたり、私がパッと思いつくのは、文字列検査とかでしょうかね。
ユーザーが入力した文字列を検査して問題が無ければ次の処理へ受け渡す……みたいな。
応募フォームだとかアンケートフォームだとかは、ユーザーに文字列なり数値なりを入力させて、それを受け取り集計するわけですが、入力された値がデータ的に正しいかどうか(電話番号が数値で記述されているか?等)の検査はどの文字列に対しても行う必要があります。
それぞれの項目ごとに個別に処理を記述していては何度も同じコードが登場する事になり、可読性が低下します。

そこで、受け取った文字列を検査して、問題があるかどうか判断して結果を返す"プロシージャ"を作成して、必要に応じて呼び出すようにすれば、文字列検査の処理は一度記述するだけで済みます。
意味的に単一な処理はすべて"プロシージャ"としてまとめ、呼び出し元となるソースコードには、その"プロシージャ"を呼び出す順番だけが記述されるようになるのが理想的ですが、まあそこまで綺麗なソースコードはそうそうないですね。


メインSubプロシージャとサブSubプロシージャ

あなたが作成するSubプロシージャは先に説明した通り、呼び出す側と呼び出される側に区別する事ができます。
これはプログラミングにおいて一般的に"メインルーチン"と"サブルーチン"と区別して呼ばれるものです。
呼んで字のごとく、"メインルーチン"は主たる処理なので呼び出す側、"サブルーチン"は副たる処理なので呼び出される側です。

しかし、Visual Basic for Applications(VBA)では、Office付属のVisual Basic Editor(VBE)でやってみればわかるが、コードの書き出しはすべて"Sub"なのである。
つまり、主たる処理となるメインルーチンも"Sub"プロシージャとして記述する事になるのだが、この"Sub"は実は"Subroutine"の略なので、メインルーチンなのに"Subroutine"という意味のわからない状況に陥る。
要するにメインSubプロシージャと、サブSubプロシージャが存在することになるわけだ。

これはおそらく、そのVBAを使用するOfficeファイルをメインルーチンとして見立てているためではなかろうか?と思うのだが、詳細は設計した人に聞いてほしい。調べてもさっぱりわからん。
余談だが、変数を宣言する際に使用される"Dim"ステートメントも同様の矛盾をはらんでいる。
すなわち、"Dim"とは"Dimension(次元)"の略で、本来は"配列"を意味するが、VBAでは配列以外の変数もひとくくりで"Dim"を使用して宣言している。
勉強を始めた人間のうち、特に公式に意味を求める(voidが気になって先に進めない)タイプの人は陥りやすい罠だが、時に意味を知らない方が効率が良い要素も存在するものだ。これこそまさに『そういうものだ』と覚えておくに限る。
変数を宣言する時は"Dim"、プロシージャの開始は"Sub(あるいはFunction)"、それだけわかっていれば十分だ。


"Sub"プロシージャと"Function"プロシージャの違い

調べた限りでは戻り値があるかどうかが両者を分かつポイントのようです。
そういう意味で、両者は"メソッド"と"関数"の違いに近いですね。
比較するとこんな感じかな?
比較対象 デフォルトで用意 ユーザーが作成 引数 戻り値 Callステートメント
メソッド × × 使用可
関数 × 使用可、戻り値必要なら使わない
Subプロシージャ × × 使用可
Functionプロシージャ × 使用可、戻り値必要なら使わない
ステートメント × × × -

例外とかあるかもですが、とりあえずこんな感じっぽい(自信無い)。



以下更新中



最終更新:2013年06月05日 13:22