ブックに属する名前とシートに属する名前(2)

昨日に続き、Nameプロパティについて。教わったことや試してみたことを、いくつか備忘録として残しておく。

f:id:Infoment:20181007062510p:plain

実験

セルに名前を付けて、その値を複数の方法・条件で参照してみる。

名前を指定してセル選択

A1に「氏名」と名付けた状態で、名前ボックスにセル番地を入力すると、A1に移動する。
f:id:Infoment:20181007063036g:plain

名前ボックスはドロップダウンボックスなので、名前を選択することも可能。
f:id:Infoment:20181007063204p:plain

マクロで名前を指定して値取得

上記「氏名」に「山田太郎」と入力されている場合。
「氏名」というセルの名前で「山田太郎」の値を取得する方法は、以下の二通り。

Sub NameTest()
    MsgBox Range("氏名").Value
    MsgBox ThisWorkbook.Names("氏名").RefersToRange.Value
End Sub
複数の同じ名前を参照する場合の優先順位

A1の名前が「氏名」の状態で、シートをコピー。すると、コピー先のA1も「氏名」という名前になる。

  • コピー元の「氏名」・・・ブックに属する名前
  • コピー先の「氏名」・・・シートに属する名前

コピー先「氏名」の値を、「村岡花子」に変えてみよう。この状態で、元のシートを選択し、先ほどのマクロを実行してみる。

結果は、共に「山田太郎」が表示される。これは、何となく予想通り。

次いで、コピーしたシートがアクティブな状態で、つまり「村岡花子」が表示されている状態で、同マクロを実行する。結果は、以下の通り。

Sub NameTest()
    ' ↓ 「村岡花子」が表示される。
    MsgBox Range("氏名").Value
    ' ↓ 「山田太郎」が表示される。
    MsgBox ThisWorkbook.Names("氏名").RefersToRange.Value
End Sub

もう一つ。
シート先に属する名前「氏名」だけを削除して、再度、同マクロを実行する。このとき、アクティブシートのA1には「村岡花子」が表示されたままである。結果は、以下の通り。

Sub NameTest()
    ' ↓ 「山田太郎」が表示される。
    MsgBox Range("氏名").Value
    ' ↓ 「山田太郎」が表示される。
    MsgBox ThisWorkbook.Names("氏名").RefersToRange.Value
End Sub

この実験から、以下のことが分かる。
① Range("セル名称") が参照する、同じ名前の優先順位

  1. アクティブシートに属する名前
  2. ブックに属する名前

② ThisWorkbook.Names("セル名称").RefersToRange が参照する、
  同じ名前の優先順位

  1. ブックに属する名前のみ

※↓↓---------------------公開後追記---------------------↓↓
Imiitoさんから、ご指摘いただいた(いつも有難うございます)。
ThisWorkBook.Namesの優先順位は、

  1. 最も左のワークシートに属する名前
  2. ブックに属する名前

試しにシートの並びを入れ替えたところ、↓ 以下の結果になった。

Sub NameTest()
    ' ↓ 「山田太郎」が表示される。
    MsgBox Range("氏名").Value
    ' ↓ 「村岡花子」が表示される。
    MsgBox ThisWorkbook.Names("氏名").RefersToRange.Value
End Sub

シートの並びによって、得られる結果が正反対になってしまった。
※↑↑---------------------公開後追記---------------------↑↑

前者は、状況によって結果が自動的に変わってしまう。上手く使えば便利なのかもしれないが、意図しない結果が返ってくることもある。
使いどころとしては、例えば同じ書式のシートが複数ある場合。1シートにつき1名の社員情報を管理していて、これが複数ある場合など。


後者は、同じ名前が複数あってもブックに属する名前を参照する。意図しない名前の複製が生じていたとしても、問題なくオリジナルを参照可能となる。

※↓↓---------------------公開後追記---------------------↓↓
Imihitoさんからのご指摘により、こちらも訂正。上記(後者)は、オリジナルのシートが最も左にいる場合のみに成立する条件となる。従って、状況によって結果が自動的に変わってしまうのは、こちらも同じだった。
※↑↑---------------------公開後追記---------------------↑↑

なお、別のシートにある「シートに属する名前」を指定するには、シートも指定すれば良いようだ。

Sub NameTest()
    ' Sheet1の山田太郎ではなく、村岡花子が表示される
    MsgBox Sheets("Sheet1 (2)").Range("氏名").Value
End Sub

結論

それぞれの方法に、メリットとデメリットあり。
その特性を正しく理解し、正しく活用しよう。

なんて書いておきながら、忘れたころに、自分もうっかり失敗しそうです。

参考まで。