
Microsoft Officeの旧バージョンで作成されたVBAマクロ(Excel、Access)を最新バージョンのOfficeや最新OSで動かそうと思っても、そのままでは動かないというケースはとても多いです。
VBAマクロが動かなくなる理由は様々なのですが、その中でも
VBAマクロ内で使用されているDLL(Win32API)が新PCで動かずにエラーが発生する
というのは、よくあるパターンの1つです。
DLLが原因でVBAマクロが動かないというのは、主に次のケースで発生します。
- PCの入れ替えに伴いWindowsのバージョンを変えた(Windows7→Windows10)ら、今まで使えていたマクロが動かなくなった
- Accessをバージョンアップしたら動かなくなった
- 32bit版のAccess/Excelから64bit版のAccess/Excelに変えたら動かなくなった
- AccessからAccess Runtimeに変えたら動かなくなった
例として4つほど上げましたが、今まで動いていたVBAマクロが動かなく場合、大抵はこれらのどれかに当てはまることが多いです。また、場合によっては複数に当てはまっているケースもあり得ます。
いっそのこと過去に作られたVBAマクロは使わないようにしたいところですが、中々そういうわけにもいかないことも多いです。VBAマクロが使えないことで場合によっては業務が止まってしまう可能性もあり、どうにか継続利用できるようにしたいというのは出てきて当然の声だと思います。
動かなくなったVBAマクロを動かせるようにするには、次の状況がそろっている必要があります。
- VBAマクロを作った人に修正をお願いする
または
- PCにMicrosoft Officeがインストールされている(Runtimeではなく)
- VBAの知識がある(デバッグできる)
VBAマクロを作った人がいるならばその人にお願いすれば修正してくれると思いますが、いない場合は自力で解決するか誰かにお願いするかが必要です。自力で解決する場合はVBAの知識が無いとまず修正することはできません。
今回の記事ではVBAの知識がある方に向けて、VBA内で使用しているDLL(Win32API)を64ビット環境で動くように修正対応する方法をご紹介します。
色々なサイトで対応方法は載っていますが、個人的にわかりづらい部分が多かったので、わかりやすいように流れを整理してみました。
VBAを使っているような場合で特にWin7からWin10へのPCの入れ替えを行ったら動かなくなったという方は参考になるかと思います。
この記事の目次
DLLが原因でVBAマクロが動かない理由
DLLが原因でVBAマクロが動かなくなる最大の理由は、PCにインストールされているOfficeのバージョンです。ここで指しているバージョンというのは、Access 2010/2013/2016/2019のようなバージョンではなく、32bit版なのか64bit版なのか、ということです。
この理由により、VBAマクロが動かないというのはほぼ間違いなく、次のような環境になっていると想定されます。
- VBAマクロは32bit版で作られているファイルである
- 64bit版のOfficeがインストールされているPCで動かそうと思ったら、エラーが出て動かない!
元々Windowsは32bit版のみで、それに伴いOfficeも32bit版しかありませんでした。
それが、PCに搭載されるメモリが2GBを超え始めたころから性能を最大限利用するために64bit版が出始めて、Officeも32bit版と64bit版の2種類存在するようになりました。(たぶん・・)
Officeの64bit版が出始めたころは、32bit版から64bit版に変えたら色々と問題が出たようで、Microsoftとしても32bit版が推奨していました(確か・・)
で、なんやかんやあって、記事投稿時点(2020年6月時点)ではOfficeのバージョンは特に気にされなくなって、64bit版が多く使われるようになっていると思います(たぶん・・・)。
参考:64 ビット版または 32 ビット版の Office を選択する
ということで、
- 32bit版で作成したマクロを32bit環境で利用していた(例えばWindows7 & Office2010 32ビット版)
- パソコンが古くなったのでWindows10への買い替えついでにOfficeも最新バージョンにした(この時に特に気にせず64ビット版のオフィスを購入)
- Windows10 & Office 64bit環境でVBAマクロを動かしたところ、動かなくなった
というのが、今まで動いていたマクロが動かなくなった状況として多いのではないかと思います。
動かなくなったという方は、まず動かないPCにインストールされているOfficeが32ビットなのか64ビットなのかを確認してみましょう。
DLLを64bit環境でも動くようにするための手順
VBA内で使用されているDLLはWin32APIなので、32ビット用のAPIです。
そのため、これを64ビット環境でも動くように修正をする必要がありますので、次の手順で該当箇所を修正してみましょう。
VBAソース内を「.dll」「Declare」で検索して修正箇所をブックマーク
まず、ファイルを開きます。
Accessファイルの場合、起動時にマクロが動いてしまってエラーメッセージが表示され強制終了してしまうようなケースがあります。このような時は、Shiftキーを押しながらAccessファイルを開くとマクロが実行されずにAccessファイルを開くことができます。
次に、Visual Basic Editorを開き、VBAのソースをどれでもいいので表示します。

この状態でctrl+fをクリックして検索ボックスを表示し、dllと入力、対象を「カレント プロジェクト(C)」にチェックして、次を検索ボタンをクリックします。

該当する部分が表示されますので、この状態でツールバーの青い旗をクリックしてブックマークします。

カーソルがある行にブックマークが設定されます。ブックマーク後はこのように目印が表示されるようになります。

これをVBAソース内のすべての該当箇所に対して行います。
- dll または Declareで検索する
- ヒットした行をブックマークする
- 次を検索する
- ヒットした行をブックマークする・・・
これで、修正すべき箇所に対して全てブックマークすることができました。
Visual Basic Editorにブックマーク用のツールバーが表示されていない場合、
メニューの「表示」→「ツールバー」→「編集」
にチェックを入れることで表示されるようになります。
合わせて「標準」にもチェックを入れておくとよいでしょう。

ブックマークをすることで、ブックマーク移動ボタンから次のブックマークに遷移することができるようになります。

ブックマークをすることで都度検索の手間が省けますので、使ってみましょう。
外部API宣言の定義部分のソースを修正
次に、外部API宣言部分のソースを修正します。
修正時のポイントは次の3つです。
- 関数の宣言に「PtrSafe」を付ける
- 64bit版での動作用に条件分岐して定義する(必要な場合)
- Long型で参照型パラメータとなっている部分をLongPtrに変更する
関数の宣言に「PtrSafe」を付ける
64bit版で動作させるようにする場合、API呼び出し用の関数にPtrSafeを付ける必要があります。64bit版で動作させるためにこれは必須の設定となるため、必ず設定します。
Private Declare Function SHGetPathFromIDList Lib "shell32.dll" Alias "SHGetPathFromIDListA" _ (ByVal lxDigital As Long, _ ByVal lxFolderPath As String) As LongPtr
↓
Private Declare PtrSafe Function SHGetPathFromIDList Lib "shell32.dll" Alias "SHGetPathFromIDListA" _ (ByVal lxDigital As LongPtr, _ ByVal lxFolderPath As String) As LongPtr
64bit版での動作用に条件分岐して定義する(必要な場合)
マクロを利用するPC環境として32bit版と64bit版が混在するような場合、関数の定義をそれぞれで動かすために条件分岐を行います。
条件分岐は次のように、IFの前に#を追加したコードを書きます。
'API:フォルダのパスを取得する Private Declare Function SHGetPathFromIDList Lib "shell32.dll" Alias "SHGetPathFromIDListA" _ (ByVal lxDigital As Long, _ ByVal lxFolderPath As String) As LongPtr
↓
#If VBA7 Then 'API:フォルダのパスを取得する Private Declare PtrSafe Function SHGetPathFromIDList Lib "shell32.dll" Alias "SHGetPathFromIDListA" _ (ByVal lxDigital As LongPtr, _ ByVal lxFolderPath As String) As LongPtr #Else 'API:フォルダのパスを取得する Private Declare Function SHGetPathFromIDList Lib "shell32.dll" Alias "SHGetPathFromIDListA" _ (ByVal lxDigital As Long, _ ByVal lxFolderPath As String) As LongPtr #End If
If VBA7 Then の中に64bit版用の宣言を書き、#Elseの中に32bit版用の宣言を書きます。
厳密にはVBA7での判定だけではなくWin64での条件分岐も必要なようですが、VBA7だけでも動くのでここではWin64での判定は行っていません。
Long型で参照型パラメータとなっている部分をLongPtrに変更する
関数でLong型を使用している場合、LongPtrに変更します。
注意点としては、参照型の部分のみLongPtrに変えるということです。Long型の部分を全てLongPtrに変えるということではありません。
また、パラメータの他に、関数の戻り値、関数のパラメータで使用している構造体もあわせて変更する必要があるので、忘れずに変換するようにしましょう。
とはいえ、使いたい関数がLong型を使っている場合に、どの部分がLongの参照型でLongPtrに変える必要があるのかを見つけるのは中々めんどくさいです。
そんな方のために、以下のサイトにWin32API_PtrSafe.TXTがあるのを見つけました。
このテキスト内を関数名で検索し、その関数部分をコピペすれば基本的には64bit環境で使えるようになりますので、参考にしてみて下さい。(構造体の宣言も記載されているので、合わせてコピペしましょう)
宣言部分の関数を使用している部分のソースを修正
基本的には関数の宣言部分のみ変更すれば64bit版環境でもVBAが動くようになりますが、中にはそれだけでは動かないケースがあります。
その最たる例がGetSaveFileNameを利用してダイアログ表示する場合です。
GetSaveFileNameの場合、この関数を利用して構造体のサイズをlStructSizeに設定しますが、64bit環境ではLenBを使用する必要があります。32bit環境ではLenで動きますが、64bit環境ではLenでは動かない(エラーが出ない代わりにダイアログも出ない)という状況になります。
Dim OFN As OPENFILENAME 'OPENFILENAME構造体 Dim Ret As Long '戻り値 With OFN '構造体の設定 .flags = OFN_PATHMUSTEXIST Or _ OFN_FILEMUSTEXIST Or _ OFN_HIDEREADONLY Or _ OFN_OVERWRITEPROMPT 'Or OFN_SHOWHELP .hInstance = 0 'インスタンスハンドルを設定 .hwndOwner = nHandle 'ウインドウハンドルを設定 .lpstrTitle = "ファイルを保存する" 'コモンダイアログのタイトルを設定 .lpstrFilter = nFilter 'フィルターを設定 #If VBA7 Then 'VBA7(64bit)時 .lStructSize = LenB(OFN) '構造体のサイズを設定 #Else .lStructSize = Len(OFN) '構造体のサイズを設定 #End If .nMaxFile = 250 'ファイル名のバッファサイズを設定 .lpstrFileTitle = String(250, Chr(0)) 'フルパス用のバッファを確保 .nMaxFileTitle = 250 'フルパス用のバッファサイズを設定 .lpstrFile = String(250, Chr(0)) 'ファイル名のバッファを確保 '.lpstrInitialDir = CurDir 'デフォルトのディレクトリを設定 End With Ret = GetSaveFileName(OFN) If Ret = 0 Then SaveDlg = vbNullString Else SaveDlg = Left$(OFN.lpstrFile, InStr(OFN.lpstrFile, Chr$(0)) - 1) 'パスを取得 End If
関数の引数の型を修正
64bit環境用に関数定義を変更した場合、引数がLong型からLongPtr型に変わるケースがあります。
そのため、関数の引数に渡している変数もLongPtr型に変更する必要があります。
ここは意外と忘れがちで、実行時に「型が違います」というエラーが出て発覚することがあるため、忘れずに修正します。
構造体がWin32APIの引数に定義されている場合、構造体内の定義も忘れずにLong型→LongPtr型に変わっている部分が無いかを確認します。変更を忘れた場合、処理の途中でAccessが強制終了(落ちる)ようなケースがたまに発生します。
まとめ
VBA DLL(Win32API)を64ビット環境で動くように修正対応する方法についてご紹介しました。
ちょっと躓くポイントを記載しましたので、参考になれば幸いです。