7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

VBAの感嘆符演算子

Posted at

#概要
AccessVBAのサンプルコードで「Me!TextBox」のように「.」ではなく「!」で繋げているものがあって気になったので調べると感嘆符演算子というものらしい。
(自動翻訳が半端でMSのページではよくわからない名前になってるが感嘆符演算子でいいはず)
参考:MSのリファレンス

##例と謎

UserForm1.frm
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")」と等価だと思うのだが、なぜか前者だけ候補が出てくる。
感嘆符演算子でアクセスしても型による候補が有効になるのは知る限りフォーム特有の動きなので、なにか特殊な処理があるのかそれこそがディクショナリアクセスというものの性質なのか……。

##使い方

ADODB.bas
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では大文字と小文字が新しく宣言された変数名等によって変わることがあるのでそこで意図しない動きをすることがあるかもしれない。
そのまま使えない文字列については「[]」で囲うことで指定できる。

###他の使い方

Dictionary.bas
'渡す側
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を作る必要があるのでそこだけは手間。

7
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?