和風スパゲティのレシピ

日本語でコーディングするExcelVBA

Excelがスピルに対応したバージョンか調べる

Excelがスピル対応のバージョンか調べる方法を解説します。

一発で調べる方法はありませんので、
RangeオブジェクトにFormula2プロパティが存在するかで判定します。

ソースコード

Sub Excelがスピルに対応したバージョンか調べる()

    Dim Range変数 As Range
    Set Range変数 = Worksheets("○○").Range("A1")
    
    ' エラースキップ下でFormula2を取得してみる
    On Error Resume Next
    Dim tmp: tmp = Range変数.Formula2
    Dim isスピル対応 As Boolean
    isスピル対応 = Not (Err.Number = 438)
    On Error GoTo 0
    
    If isスピル対応 Then
        
        ' Formula2を用いてスピルを利用したマクロなど

    End If
        
End Sub

解説

Excelがスピルに対応しているか調べるには、
RangeオブジェクトにFormula2プロパティが存在するかを判定します。


RangeオブジェクトにFormula2プロパティがない場合は、

実行時エラー '438':
オブジェクトは、このプロパティまたはメソッドをサポートしていません。

エラーが起こりますので、これを判定するわけですね。


On Error Resume Nextを利用したコードのため、
即座にOn Error GoTo 0 を実行したいのですが、

On Error Resume Next
Dim tmp: tmp = Range変数.Formula2

If Err.Number = 438 Then

このように直接Err.Numberを使って分岐をすると、
On Error GoTo 0 を書く場所にちょっと困ります。


なので上記コードのように、一旦フラグ変数に入れて、
Ifステートメントの判定はその変数を使用するのがおすすめです。

' エラースキップ下で一旦True/Falseを取得
On Error Resume Next
Dim tmp: tmp = Range変数.Formula2
Dim isスピル対応 As Boolean
isスピル対応 = Not (Err.Number = 438)
On Error GoTo 0

' 分岐はフラグ変数を使って行う
If isスピル対応 Then

スピル対応か判定する汎用関数

この判定をよく行う方は、汎用関数化しておくと便利です。

Function IsExcelがスピル対応バージョン() As Boolean
    On Error Resume Next
    Dim tmp: tmp = Workbooks(1).Worksheets(1).Range("A1").Formula2
    IsExcelがスピル対応バージョン = Not (Err.Number = 438)
    On Error GoTo 0
End Function

' 使用例
If IsExcelがスピル対応バージョン Then
    ' Formula2を用いてスピルを利用したマクロなど

メインコードが1行になって非常に便利ですね。


この手のOn Error Resume Next利用コードは、
簡単な割にコード量が多いためメインコードの邪魔になります。

汎用関数化しておくと非常に書きやすく&読みやすくなりますので、
この処理をよく行う場合は汎用関数化をおすすめします。

おまけ:Rangeオブジェクトとコンパイルエラー

本来オブジェクトにプロパティが存在するかを判定する場合は、
以下のコードのように「As データ型」を指定してはいけません。

Dim ws As Worksheet
Set ws = ActiveSheet

On Error Resume Next
Dim tmp: tmp = ws.Value
Dim WorksheetにValueがあるか As Boolean
WorksheetにValueがあるか = Not (Err.Number = 438)
On Error GoTo 0

このコードは「WorksheetオブジェクトにValueプロパティが存在しない」ため、
そもそも実行することができずコンパイルエラーとなります。

もちろんコンパイルエラーはOn Error Resume Nextできません。


よって本来オブジェクトにプロパティが存在するか調べるには、

Dim ws As Variant
Set ws = ActiveSheet

と、Variant型変数にしてコンパイルエラーを回避する必要があります。


これが通常のオブジェクトの話なのですが、
Rangeオブジェクトの場合は話が異なります。


Rangeオブジェクトは「省略時はValue」と思われがちですが、より正確には、

  • オブジェクトが求められる場面ではRangeそのもの
  • 値が求められる場面ではRange.Value
  • 引数を渡した場合はRange.Item(r, c)

が省略時の挙動となります。

そしてこの挙動を再現するために、
Rangeオブジェクトの規定のメンバーは[_Default]プロパティとなっています。


この[_Default]プロパティの返り値はVariant型で、以下の仕様になっています。

Cells(R, C) ' ←これはCells.[_Default](R, C)の省略形
    ' 実はCellsプロパティには引数がなく、Cells(R, C).で入力候補が出ない原因がこれ

Range("A1")(2, 2) ' ← これはB2セルを指す。Cellsと同じことをRangeもできる
    ' これはRange("A1").[_Default](2, 2)の省略形

Range("A1").ああああ ' ← !なんとこれはコンパイルエラーにならない!
    ' Range("A1").[_Default] がVariant型のため「ああああ」もコンパイルが通る

この3つ目の挙動を使うことで、
Range.Formula2をコンパイルエラーなく記述できるわけですね。

一応知らなくても今回のコードは問題なく使用できますが、
せっかくなので頭の片隅にでも置いておいてください。