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をコンパイルエラーなく記述できるわけですね。
一応知らなくても今回のコードは問題なく使用できますが、
せっかくなので頭の片隅にでも置いておいてください。