動くはずの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を使っていないか
    →自作を検討する
  • 仕様がことなる関数を使っていないか
    →その関数を使わない
    →呼び出し方(引数など)をチェック