Worksheets.Item()がObject型を返す理由の妄想

結論

シートモジュールのせい。

(18/07/07 追記

引数にインデックス・名前の配列を渡すと、Excel.Sheets型で返されるため、純粋に「返すオブジェクトの種類が固定ではない」せいとなります。

Dim s As Object
Set s = Worksheets.Item(Array("Sheet1", 2))

Debug.Print TypeName(s) '-> Sheets

以下は以前の記事の内容になります。

結論への経緯

ワークシートはWorksheet型ではない

Excelのワークシートは、厳密に言うとWorksheet型ではありません(ワークシート以外にもシートの種類はありますが、それらについても同様です)。

では何か?と言うとWorksheet型をベースに拡張された、各シート固有の型となります。 これらの型は一つとして同じ物はありません。

そのため、Worksheet型として扱うとWorksheetとしての共通機能は使用できますが、各シート固有の機能は使用できません。

補足:各シート固有の部分

  • シート上のActiveXコントロール(オブジェクト名のプロパティになります)
  • シートモジュール内で定義された広域変数(プロパティ相当のものになります)
  • シートモジュール内で定義された広域プロシージャ

シートの参照方法

ワークシートを参照する方法には以下の2種類があります。

  1. Sheet1などのシートオブジェクトを直接参照
  2. Worksheets.Item()による名前・番号を指定した参照

1の場合、Worksheetよりも具体的な型で取得できるため、各シート固有の機能を使用できます。 ただし、プロジェクト外部から使用したい場合は参照設定が必要になります。

2の場合、Worksheets.Item()の返り値がObject型であるため、正しい名前を指定すれば各シート固有の機能を使用できます。 プロジェクト外部からでも、名前などが正しければ使用できます。

仮に返り値がWorksheet型の場合、一度Object型や各シート固有の型にキャストしないと各シート固有の機能を使用できません。

Worksheets.Item()がWorksheet型だと問題になる例

実際にそれぞれのシートが別の機能を持っているならば「Sheet1などのシートオブジェクトを直接参照」で処理をすれば問題はありません。

しかし「同じ形式のシートが複数枚存在し、それぞれに対して同じ処理をしたい」といったことがあった場合、 返り値がWorksheet型だと何らかの型変換が必要になってしまいます。

'm番目からn番目のシート上にある、
'`CommandButton1`という名前のActiveXコントロールのキャプションを表示する
For i = m To n
    
    '`Worksheets.Item()`がObject型の場合
    Debug.Print Worksheets.Item(i).CommandButton1.Caption '直接参照でOK
    
    '`Worksheets.Item()`がWorksheet型の場合
    Dim tmp As Object
    Set tmp = Worksheets.Item(i) '要キャスト
    Debug.Print tmp.CommandButton1.Caption
    
Next i

このあたりを良い感じに処理できるようにするために、Sheets型という汎用的な型でWorksheetsを表しているのではないかと思います。