#概要
AccessVBAのサンプルコードで「Me!TextBox」のように「.」ではなく「!」で繋げているものがあって気になったので調べると感嘆符演算子というものらしい。
(自動翻訳が半端でMSのページではよくわからない名前になってるが感嘆符演算子でいいはず)
参考:MSのリファレンス
##例と謎
Private Sub TextBox1_Change()
Debug.Print TextBox1.Value, "Meを省略して使う場合"
Debug.Print Me.TextBox1.Value, "Meを入れた使い方"
Debug.Print Me!TextBox1.Value, "Meと感嘆符を使う場合"
Debug.Print Me("TextBox1").Value, "Meから直にTextBox1を文字列で指定する場合"
Debug.Print Me.Controls!TextBox1.Value, "Controlsから感嘆符を使う"
Debug.Print Me.Controls("TextBox1").Value, "ControlsのItemを省略する"
Debug.Print Me.Controls.Item("TextBox1").Value, "Itemも省略せずに使う"
End Sub
説明によると文字を引数として受け取るデフォルトプロパティにリテラルを直に渡して呼び出せるものらしい。
上記のフォームのTextBox1のValueを呼び出す処理は全部正しく動作する。
上の3つはValueの上でCtrl+Jを押すと候補が出てくるが、4番目以降の方法では候補が出ない。
これはどれもControls.Item("TextBox1")の省略形で、Controls.Itemの戻り値はObject型なので候補が出ないのは分かる。
謎なのは3番目だ。
「Me!TextBox1」は「Me.Controls.Item("TextBox1")」と等価だと思うのだが、なぜか前者だけ候補が出てくる。
感嘆符演算子でアクセスしても型による候補が有効になるのは知る限りフォーム特有の動きなので、なにか特殊な処理があるのかそれこそがディクショナリアクセスというものの性質なのか……。
##使い方
Dim Recordset As ADODB.Recordset
Set Recordset = New ADODB.Recordset
Dim Connection As ADODB.Connection
Set Connection = New ADODB.Connection
Connection.Open "いろいろ"
Recordset.Open "SQL", Connection
With Recordset
Do Until .EOF
Debug.Print !名前.Value, !番号.Value, ![空白も 行ける].Value
Loop
End With
ADODBを使った例でRecordsetに対して感嘆符演算子でアクセスしているものをたまに見る。
これはRecordset.Fields.Item("名前").Valueと同じ挙動をする。
データベースのフィールド名は常に固定なので処理によってはこれで十分動く。
ただしアルファベットを使ったフィールド名の場合はVBEでは大文字と小文字が新しく宣言された変数名等によって変わることがあるのでそこで意図しない動きをすることがあるかもしれない。
そのまま使えない文字列については「[]」で囲うことで指定できる。
###他の使い方
'渡す側
Dim Dic As Scripting.Dictionary
Set Dic = New Scripting.Dictionary
With Dic
!Name = ThisWorkbook.Name
!FullPath = ThisWorkbook.FullName
Set !Book = ThisWorkbook
Set !Dic = New Scripting.Dictionary
With !Dic
!Nest = "入れ子もできる"
End With
End With
'受け取り側
With Dic
Name = !Name
FullPath = !FullPath
Set Book = !Book
Nest = !Dic!Nest
End With
変な使い方としてはDictionaryで使う。
Dictionaryは存在しないキーを指定して値を設定すると新規キーとしてその値を登録できる。
汎用インタフェースを使って引数を渡す場合に使うとParamArrayと違って役割が明確になる。
すべてVariant型になるのはParamArrayと同じだが、毎回渡すためだけにDictionaryを作る必要があるのでそこだけは手間。