動くはずのVBAがMacでエラーになったときの解決策と着眼点
エクセルのVBAはかなり便利な反面、WindowsとMacの間で完全に互換性があるわけではありません。
こっちの端末では動くけど、あっちの端末では動かない…。
このブログではエクセルの各種テンプレートを無料配布しているので、そんなやっかいな現象にたくさん悩まされてきました。
というわけで今回は、「動くはずのVBAがMacでエラーになったときの解決策と着眼点」と題して、いくつかポイントを共有します。
Contents
参照設定はできるだけ控える
エクセルがどんな端末で動かされるか想定できない場合は、できるだけ参照設定をいじくらないのが無難です。
たとえば、Dictionaryオブジェクトを使うための「Microsoft Scripting Runtime」。
こちらの画像の下部にあるとおり、“Windows"というフォルダに入っているDLLを読み込んでいるため、“Mac"ではおそらくエラーになります。(実際になりました)
CreateObject(“Scripting.Dictionary”) のように動的に読み込んだとしても、とくに変わらないかと思います。
こういうときは、ちょっとだけ大変だけどクラスモジュールとして自分で作ってしまうのがベスト。
といってもすべての機能を組み込む必要はなくて、自分が使いたいところだけコーディングすればいいのです。
私の場合はDictionaryオブジェクトのAdd、Exists、Itemが使いたかったので、その3つだけ実装しました。
'Microsoft.Scripting.RuntimeのDictionaryを再現するクラス
'MacにはDictionaryが採用されていないため作成
Option Explicit
Private keys As New Collection
Private values As New Collection
Public Function Add(ByVal key As String, ByVal value As Variant)
If Exists(key) Then
Err.Raise 457
Else
keys.Add key, key
values.Add value, key
End If
End Function
Public Function Exists(ByVal key As String) As Boolean
Dim k As Variant
For Each k In keys
If k = key Then
Exists = True
Exit Function
End If
Next k
Exists = False
End Function
Public Property Get Item(ByVal key As String) As Variant
If Exists(key) Then
Item = values.Item(key)
Else
Me.Add key, Empty
Item = Empty
End If
End Property
Dictionary以外でいうと、Microsoft標準のカレンダーコントロールも使いたかったのですが、同じ理由で自作することにしました。
強引にエラーを回避する手段もあるかもしれませんが、安定性という意味では「自作」に勝るものはありません。
⇒【完成品】エクセルVBAでカレンダーフォームを作成してみた!仕様がことなる関数を使わない
VBAには、WindowsとMacで仕様がことなる関数がちょこちょこ存在します。
そういう関数もできるだけ使わないようにしましょう。
一例としては、指定したウィンドウをアクティブにするAppActivate
あるフォームを表示した直後にフォーカスを同フォームからエクセル本体に戻す…っていう意味で、 以下のコードを書きました。
AppActivate Application.Caption
まあまあよくあるコードだと思いますが、環境によってはエラーになることがあります。
原因はよくわかりません(笑)
ただし、私の他にも同じことで苦悩している方がいるので、実際に起こりうることです。
そういう意味で AppActivate はやっかいな関数であるため、できるだけ使わないようにした方がいいみたいですね。
もうひとつの例は、ファイルを選択させるための GetOpenFilename という関数。
コードはこんな感じで、ファイルの選択ダイアログを開くやつです。
Dim path As Variant
path = Application.GetOpenFilename("Microsoft Excelブック,*.xls?")
If path <> False Then
'ファイルを操作する処理
End If
このコード、Macではなぜかエラーになってイラっとしたことがあります。
調べてみると、GetOpenFilename の仕様としてMacではファイルのしぼり込みができないのだとか。
しぼり込むのはあきらめて、以下のように引数を消去すると動きました。
Dim path As Variant
path = Application.GetOpenFilename()
If path <> False Then
'ファイルを操作する処理
End If
ユーザーフレンドリーなのはファイルをしぼり込んでくれる前者のコードだけど、エラーで落ちてしまうのは論外です。
WindowsでもMacでも動くように、OSによって動作が変わってしまう関数の呼び出し方は避けるのがおすすめです。
動くはずのVBAがMacでエラーになったら
ここまでの内容をまとめて、動くはずのVBAがMacでエラーになったときのチェックリストを作りました。
この記事で紹介したものの他にも、たくさんの事例があるはずですが、着眼点としてはこんな感じかと思います。
- 参照設定を増やしていないか
→自作を検討する - CreateObjectを使っていないか
→自作を検討する - 仕様がことなる関数を使っていないか
→その関数を使わない
→呼び出し方(引数など)をチェック