Excel VBA アドレスを[A1]と表記できる理由と長所と欠点


Evaluate

どんなワークシート関数でも実行する Excel97 Later Moug](https://www.moug.net/tech/exvba/0100045.html)
WorkSheetFunctionですべての関数が実行できるわけではない。
VBAの関数が存在する場合、VBAが優先される。
また同名の関数以外でも呼び出せないものがあり、そういう場合はEvaluate関数を使う。
そしてその省略形が、ブラケット、角かっこ、大かっこである[]である

Application.Evaluate メソッド


  • Microsoft Excel の名前付け規則を使用した、対象オブジェクトの数式または名前。 名前の長さは 255 文字以下にする必要があります。
  • A1 形式の参照。 単一セルに対する A1 形式の参照であれば、特に制限はありません。 ただし、このメソッドでは、参照は常に絶対参照として扱われます。

    • 結合したセルがだめなように読めるが、結合していても読める。

  • 範囲 参照と共に使うことのできる演算子には、セル範囲を表す参照演算子 (:)、セル参照の共通部分を表す参照演算子 (スペース)、およびセル参照の複数選択を表す参照演算子 (,) があります。
  • 定義された名前。 コード記述時の言語で定義された名前を指定します。 You can specify any name in the language of the macro.

    • これは誤訳。VBAマクロで定義されている名前を指定できるという意味。

  • 外部参照 !演算子を使用して、セルまたは他のブックで定義されている名前を参照することができます。たとえば、 Evaluate("[BOOK1.XLS]Sheet1!A1")のようになります。

    • ブック名とシート名の間はなにもない。ブラケットで囲めばいらない。もっともピリオドでも良い。またSheet1の間の!もポイント。

  • Chart オブジェクト 凡例、プロットエリア、データ系列1など、任意のグラフオブジェクト名を指定して、そのオブジェクトのプロパティとメソッドにアクセスできます。 たとえば、 Charts("Chart1").Evaluate("Legend").Font.Nameは凡例で使用されているフォントの名前を返します。
  • フォームコントロール番号 ワークシートのフォームコントロールを参照するには、番号と名前を指定できます。 たとえば、ワークシートに配置されているラベル ([開発] タブ-[フォームの挿入] I- ラベル)Evaluate("Label 1").Caption = "Hello"Evaluate("1").Caption = "Hello" は、両方とも同じです。

    • この書き方はAccessも同じである。

  • https://vbae.odyssey-com.co.jp/column4/s41603.html DateDif関数で年齢を求める場合は必須となる。
  • 長いコードを短縮できる。特にRangeの省略 ws.ragen("A1") ws.[a1]

欠点

  • この書き方はワークブック名からアドレスを指定できるなど便利であり、可読性がないとは言えない。
  • しかし変数で代入できるものは単純なアドレスであり、複雑になるとエラーになる。この差がわかりづらく、変数で代入できない。
  • したがって、可変性が少ない。決め打ちならいいが、
  • Accessにも[Application.Evalメソッド](https://docs.microsoft.com/ja-jp/office/vba/api/access.application.eval)がある。こちらは文字数の制限はない。またVBAでSQLを書く場合、`between`演算子や、`In`演算子を使えるようにするにはEvalを使う。また、文字列を変数として代入する場合も、Excelより高度な文字列が使える。
  • 可読性が低いと言うか`[a1]` これはいろいろな意味がありすぎてEvaluateか判断できない。なので`[Sheet1!A1]`位は書いた方がよい。
Sub eavluetest()
' Sheet1 とSheet2の2枚
' Sheet1 のA1に1
' Sheet1 のA1に2
'が入っていて、ActivesheetをSheet1とする
Dim ws As Worksheet
Dim str As String
Dim bl1 As Boolean, bl2 As Boolean: bl1 = False: bl2 = False
For Each ws In ThisWorkbook.Worksheets
If ws.Name = "Sheet1" Then bl1 = True: Exit For
Next
For Each ws In ThisWorkbook.Worksheets
If ws.Name = "Sheet2" Then bl2 = True: Exit For
Next
If bl1 = False Then Set ws = ThisWorkbook.Worksheets.Add(before:="Sheet2"): ws.Name = "Sheet1"  '[Sheet1]はエラー
If bl2 = False Then Set ws = ThisWorkbook.Worksheets.Add(after:="Sheet1"): ws.Name = "Sheet2"
[Sheet1!A1] = 1
[Sheet2!A1] = 2
'Set ws = ActiveWorkbook!Worksheets!Sheet1 'これはエラー
Set ws = Worksheets!Sheet1 'これはいける
Worksheets![Sheet1].Activate  'これはいける
Debug.Print Worksheets![Sheet1].[A1]  'これはいける
Debug.Print "ws変数", ws.[a1].Value  'これはいける
Worksheets![Sheet1].[A1].Select  'これはいける
Worksheets![Sheet1].[$A$1].Select  ' 絶対参照はいける。しかし元から絶対参照なのでこのように書く意味はない。
Worksheets![Sheet1].[A2].Clear
Worksheets![Sheet1].[A2].Formula = "=1+2"
Debug.Print "result ActiveWorkbook " & Workbooks(1).Worksheets![Sheet1].[A2]  ' このワークブック1つだけならいける
Debug.Print "result ActiveWorkbook " & ActiveWorkbook.Worksheets![Sheet1].[A2]  'これはいける
Debug.Print "result ThisWorkBook " & ThisWorkbook.Worksheets![Sheet1].[A2]  'これはいける
Debug.Print "result ThisWorkBook " & [ThisWorkbook].Worksheets![Sheet1].[A2]  'これはいける
'Debug.Print "result " & ThisWorkbook!Worksheets![Sheet1].[A2] ' これはダメ
'Worksheets![Sheet1]![A2].Formula = "=1+2" 'これはダメ。Sheet名とアドレスの間はピリオドのみ
Debug.Print Worksheets![Sheet1].[A2].Formula
Debug.Print [A1] 'A1が表示される。アクティブシート
Debug.Print [Sheet2!A1] 'Sheet2のA1が表示される。アクティブシートではない
Debug.Print "[" & "Sheet2!A1" & "]" '文字列になる
str = "Worksheets![Sheet1].[A2].value"
'Debug.Print "result Str " & Application.Evaluate(str)
str = "A1"
Debug.Print Application.Evaluate(str).Value
str = "Sheet1!A1"
Debug.Print Application.Evaluate(str).Value
End Sub