この記事を書いていて気づいた小ネタです。
ws1.Range(ws2.Cells(1, 1),ws3.Cells(2, 2))
というコードでセル範囲を取得する場合は、
- ws1~ws3を一致させる
- ws2とws3を一致させてws1は省略する
のどちらかを満たさないとエラーになります。
この時のエラーは実は3種類あって、
- Range' メソッドは失敗しました: '_Worksheet' オブジェクト
- Range' メソッドは失敗しました: '_Global' オブジェクト-
- アプリケーション定義またはオブジェクト定義のエラーです。
のいずれかが発生します。
このエラーのうちどれが表示されるかを調べてみました。
A,B,Cの3つのシートを用意しAをActiveSheetに。
それぞれを「Worksheets」「オブジェクト名」「シート変数」で指定して、
いろいろなパターンでやった結果がこちらです。
Range親 | Cells1親 | Cells2親 | エラー |
---|---|---|---|
wsA. | wsB. | wsB. | Range失敗_ws |
wsA. | wsB. | wsC. | Range失敗_ws |
wsA. | Worksheets("B"). | wsB. | Range失敗_ws |
wsA. | Worksheets("B"). | Worksheets("C"). | Range失敗_ws |
wsA. | ws変数B. | wsB. | Range失敗_ws |
wsA. | ws変数B. | Worksheets("B"). | Range失敗_ws |
wsA. | wsA. | wsB. | Range失敗_ws |
wsA. | wsA. | ws変数B. | Range失敗_ws |
wsA. | wsA. | Worksheets("B"). | Range失敗_ws |
wsA. | wsB. | Range失敗_ws | |
wsA. | ws変数B. | Range失敗_ws | |
wsA. | Worksheets("B"). | Range失敗_ws | |
wsB. | wsC. | Range失敗_gl | |
Worksheets("B"). | Worksheets("C"). | Range失敗_gl | |
wsA. | wsB. | Range失敗_gl | |
wsA. | ws変数B. | Range失敗_gl | |
wsA. | Worksheets("B"). | Range失敗_gl | |
wsB. | Range失敗_gl | ||
ws変数B. | Range失敗_gl | ||
Worksheets("B"). | Range失敗_gl | ||
Worksheets("A"). | wsB. | wsB. | アプ/オブ定義 |
Worksheets("A"). | wsB. | wsC. | アプ/オブ定義 |
Worksheets("A"). | Worksheets("B"). | wsB. | アプ/オブ定義 |
Worksheets("A"). | Worksheets("B"). | Worksheets("C"). | アプ/オブ定義 |
Worksheets("A"). | ws変数B. | wsB. | アプ/オブ定義 |
Worksheets("A"). | ws変数B. | Worksheets("B"). | アプ/オブ定義 |
Worksheets("A"). | wsA. | wsB. | アプ/オブ定義 |
Worksheets("A"). | wsA. | ws変数B. | アプ/オブ定義 |
Worksheets("A"). | wsA. | Worksheets("B"). | アプ/オブ定義 |
Worksheets("A"). | wsB. | アプ/オブ定義 | |
Worksheets("A"). | ws変数B. | アプ/オブ定義 | |
Worksheets("A"). | Worksheets("B"). | アプ/オブ定義 | |
wsB. | Range失敗_ws | ||
Worksheets("B"). | アプ/オブ定義 |
ということで、Cells同士が違う/RangeとCellsが違うなどは一切関係なく、
Rangeの親シートの指定方法によってエラーの種類が決まるようです。
Rangeプロパティは様々な親オブジェクトがあるため、
- Rangeの親を特定できた場合はそのRangeが失敗したエラーを出す
- Rangeの親を特定できなかった場合は想定外のエラーを出す
って感じなんですかね。
一応予備知識として、
Rangeの親シート省略時はCellsのようにActiveSheetではなく、
Rangeの中身から親シートを特定しようとします。
今回の題材である
Range(wsB.Cells(1, 1), wsB.Cells(2, 2))
はActiveSheetに関係なくwsBのセル範囲を取得しますし、
Range("データ!A1")
このように「シート名!セルアドレス」という書き方をすれば、
文字列ですら別のシートを指させることもできますし、
Range("名前定義")
と、名前定義を活用した場合も別シートから取得可能です。
この「中身から親シートを特定しようとするRange」というのは、
Application.Rangeが実行されたという扱いとなります。
これが失敗すると、
- Range' メソッドは失敗しました: '_Global' オブジェクト
が出るということですね。
そしてもう一つの予備知識、
Worksheets("A")という書き方ですが、
実はこれは「Worksheetsプロパティの引数"A"」ではありません。
Worksheetsプロパティで取得したSheetsコレクションのItem("A")を省略した形というのが正しい説明です。
つまり「ただのコレクションのItem」でしかないため、
型はWorksheetsではなくVariantです。
Worksheets("A").
の入力選択肢が出ない原因がこれになりますね。
ということで、
Worksheets("A").Range(wsB.Cells(1, 1), wsB.Cells(2, 2))
は、
「そんなRangeの使い方知らんからどの親VerのRange使えばいいかわからん。
なんか定義間違ってない?」
ということで、
- アプリケーション定義またはオブジェクト定義のエラーです。
を出すのかもしれませんね。
イミディエイトでの挙動
ここまではまだ何となく理解できるのですが、
上記のコードをイミディエイトウィンドウで実行すると、なんとすべてのコードが
- アプリケーション定義またはオブジェクト定義のエラーです。
になります。
なぜ?
シートオブジェクトであるwsAがWorksheetオブジェクトかどうかは、
その親であるThisworkbookのコードに書かないとわからないから?
なんて最初は考察したのですが、イミディエイト上で変数を定義して、
「これはWorksheetだぞ」と明示してから実行しても、
- アプリケーション定義またはオブジェクト定義のエラーです。
が出ます。
どうしてもイミディエイトウィンドウで
- Range' メソッドは失敗しました: '_Worksheet' オブジェクト
を出すことができませんでした。
不思議ですね・・・
まったく同じコードなのに出るエラーが変わるという現象は、
この現象で初めて遭遇した気がします。
歯切れの悪い終わり方で申し訳ありませんが、
何かわかったらまた追記したいと思いますので、
みなさんの情報提供もお待ちしております。