Office 2010 の 32 ビット バージョンと 64 ビット バージョンとの互換性

Office 2010

概要 : 2GB 以上のデータを扱っているユーザーのために、Microsoft Office 2010 の 64 ビット バージョンが提供されるようになりました。この記事では、32 ビット バージョンと新しい 64 ビット バージョンとの互換性に関する問題、および以前の 32 ビット Office アプリケーションとそのソリューションについて説明します (7 ページ)。

Microsoft Office 2010 システムには 32 ビット バージョンと 64 ビット バージョンの両方があります。64 ビット バージョンの方がはるかに大量のデータを処理できます。Microsoft Excel 2010 で大きな数を処理する場合は、特にこの点が重要になります。

新しい 64 ビット バージョンの Microsoft Office 2010 が登場したことに伴って、新バージョンの Microsoft Visual Basic for Applications (VBA) がリリースされています。これは Microsoft Visual Basic for Applications 7.0 (VBA 7) と呼ばれるもので、32 ビットと 64 ビットの両方のアプリケーションで動作します。この記事で説明している変更点は、64 ビット バージョンの Microsoft Office 2010 にのみ適用されることに注意してください。32 ビット バージョンの Office 2010 を使用すれば、以前のバージョンの Microsoft Office で作成したソリューションをそのまま修正せずに使用できます。

メモ メモ

64 ビットのシステムであっても、Office 2010 の既定のインストールでは 32 ビット バージョンがインストールされます。そのため、Office 2010 の 64 ビット バージョンのインストール オプションを明示的に選択する必要があります。

VBA 7 では、既存の Windows アプリケーション プログラミング インターフェイス (API) ステートメント (Declare ステートメント) を更新して、64 ビット バージョンで動作するようにしなければなりません。さらに、これらのステートメントで使われているユーザー定義型のアドレス ポインターおよび表示ウィンドウ ハンドルを更新することも必要です。この点については、Office 2010 の 32 ビット バージョンと 64 ビット バージョンとの間の互換性問題および推奨解決案と共に、この記事で詳しく説明します。

64 ビット バージョンの Office 2010 で作成するアプリケーションは、より大きなアドレス空間を参照できるので、以前よりも多くの物理メモリを使用することが可能になります。そのため、物理メモリとの間でのデータ転送に費やされるオーバーヘッドが軽減される可能性があります。

アプリケーションがデータやプログラム命令の格納に使用する物理メモリ内の特定の場所への参照 ("ポインター" とも呼ばれる) に加えて、表示ウィンドウ識別子 ("ハンドル" と呼ばれる) を参照するアドレスを使用することもできます。32 ビット システムと 64 ビット システムのどちらを使用するかに応じて、ポインターやハンドルのサイズ (バイト数) が決まります。

既存のソリューションを 64 ビット バージョンの Office 2010 で実行する場合、次に示す 2 つの基本的な問題があります。

  • Office 2010 のネイティブの 64 ビット プロセスは、32 ビット バイナリをロードできません。既存の Microsoft ActiveX コントロールや既存のアドインがある場合、これはよく起こる問題です。

  • VBA には以前はポインター データ型がなかったので、開発者はポインターとハンドルを格納するために 32 ビットの変数を使用していました。Declare ステートメントを使用した場合、API 呼び出しで返される 64 ビット値は、これらの変数で切り詰められることになります。

VBA 7 は旧バージョンの VBA に代わる新しいコード ベースです。VBA 7 は Office 2010 の 32 ビット バージョンと 64 ビット バージョンの両方で使用できます。VBA7Win64 という 2 つの条件付きコンパイル定数が用意されています。VBA7 定数を使用すると、アプリケーションで VBA 7 と旧バージョンの VBA のどちらを使用しているのかをテストすることによって、コードの下位互換性を確保できます。Win64 定数は、コードが 32 ビットとして実行されるのか、64 ビットとして実行されるのかをテストするために使用します。これらのコンパイル定数の両方について、この記事で後ほど使用例を示します。

この記事の別の箇所で示すいくつかの例外を除き、32 ビット バージョンのアプリケーションを使用して動作したドキュメント (ブックとプレゼンテーションを含む) 内のマクロは、同じアプリケーションの 64 ビット バージョンでドキュメントを読み込んだ時にも動作します。

既存の 32 ビット ActiveX コントロールは、サードパーティ製のものも Microsoft が提供しているものも、64 ビット バージョンの Office 2010 と互換性がありません。ActiveX コントロールと COM オブジェクトについては、次に示す 3 つの解決策が考えられます。

  • ソース コードがあれば、64 ビット バージョンを自分で生成する。

  • 更新されたバージョンをベンダーから入手する。

  • 別の解決策を探す。

Office 2010 のネイティブの 64 ビット プロセスは 32 ビット バイナリを読み込むことができません。これには、MSComCtl の一般的なコントロール (TabStrip、Toolbar、StatusBar、ProgressBar、TreeView、ListViews、ImageList、Slider、ImageComboBox) と、MSComCt2 のコントロール (Animation、UpDown、MonthView、DateTimePicker、FlatScrollBar) が含まれます。これらのコントロールは、以前のバージョンの Microsoft Office によってインストールされており、現在は 32 ビットの Office 2010 によってインストールされます。コードを 64 ビットの Office 2010 に移行する場合に、これらのコントロールを利用する既存の Microsoft Office VBA ソリューションの代替方法を見つける必要があります。64 ビットの Office 2010 は、64 ビット バージョンの一般的なコントロールを提供しません。

VBA ライブラリとタイプ ライブラリを組み合わせれば、Microsoft Office アプリケーションの作成にさまざまな機能を使用できるようになります。ただし、コンピューターのオペレーティング システムや他のコンポーネントとの直接のやりとりが必要になることもあります。たとえば、メモリやプロセスを管理するとか、ウィンドウ、コントロールなどのユーザー インターフェイスを操作するとか、Windows レジストリに変更を加える場合などが、これに当たります。このような状況では、ダイナミック リンク ライブラリ (DLL) ファイルに組み込まれた外部関数を使用するのが最善策です。VBA でこれを行うには、Declare を使用して API 呼び出しを行います。

メモ メモ

Microsoft は、1,500 個の Declare ステートメントが含まれている Win32API.txt ファイルと、必要な Declare ステートメントを各自のコードに切り取って貼り付けるためのツールを提供しています。ただし、これらのステートメントは 32 ビット システム用なので、この記事で後ほど説明する情報に従って 64 ビットに変換する必要があります。既存の Declare ステートメントは、PtrSafe 属性を使用して 64 ビット向けとして安全だとマークされるまでは、64 ビット VBA にコンパイルされません。このタイプの変換のサンプルは、Excel MVP の Jan Karel Pieterse 氏の Web サイト (http://www.jkp-ads.com/articles/apideclarations.asp) にあります。

Office Code Compatibility Inspector ユーザー ガイド」は、PtrSafe 属性の API Declare ステートメントの構文 (必要な場合) と、適切な戻り値の型の検査に利用できるツールです。

Declare ステートメントの形式は、サブルーチン (戻り値がない) と関数 (戻り値がある) のどちらを呼び出すのかに応じて、次のどちらかになります。

Public/Private Declare Sub SubName Lib "LibName" Alias "AliasName" (argument list)
Public/Private Declare Function FunctionName Lib "Libname" alias "aliasname" (argument list) As Type

SubName 関数または FunctionName 関数は、プロシージャを VBA コードから呼び出すときに使用する名前を表しており、DLL ファイル内のプロシージャの実際の名前に置き換えます。プロシージャの名前として AliasName 引数を指定することもできます。Lib キーワードの後ろには、呼び出すプロシージャが含まれている DLL ファイルの名前を指定します。引数リストには、プロシージャに渡す必要のあるパラメーターとデータ型を指定します。

次の Declare ステートメントは、Windows レジストリ内のサブキーを開き、その値を置き換えます。

Declare Function RegOpenKeyA Lib "advapi32.dll" (ByVal Key As Long, ByVal SubKey As String, NewKey As Long) As Long

RegOpenKeyA 関数の Windows.h (ウィンドウ ハンドル) エントリは次のようになります。

LONG RegOpenKeyA ( HKEY hKey, LPCSTR lpSubKey, HKEY *phkResult );

Microsoft Visual C と Microsoft Visual C++ では、上記の例は 32 ビットと 64 ビットのどちらについても正しくコンパイルされます。なぜなら、HKEY がポインターとして定義されており、そのサイズはコードをコンパイルするプラットフォームのメモリ サイズを反映するからです。

以前のバージョンの VBA では、特定のポインター データ型がなかったので、Long データ型が使われていました。Long データ型は常に 32 ビットなので、64 ビット メモリのシステムで使用すると問題が起きます。なぜなら、上位の 32 ビットが切り捨てられるか、他のメモリ アドレスに上書きされることがあるからです。どちらの場合も、予測できない動作やシステム クラッシュを引き起こす可能性があります。

この問題を解決するため、LongPtr という真の "ポインター" データ型が新たに VBA に導入されました。この新しいデータ型を使用すれば、次のように本来の Declare ステートメントを正しく書くことができます。

Declare PtrSafe Function RegOpenKeyA Lib "advapire32.dll" (ByVal hKey as LongPtr, ByVal lpSubKey As String, phkResult As LongPtr) As Long

このデータ型と新しい PtrSafe 属性を使用すると、この Declare ステートメントを 32 ビット システムでも 64 ビット システムでも使用できます。PtrSafe 属性は、Declare ステートメントの対象を 64 ビット バージョンの Office 2010 とすることを VBA コンパイラに指示するものです。この属性を指定せずに Declare ステートメントを 64 ビット システムで使用すると、コンパイル時エラーが発生します。ただし、PtrSafe 属性は、32 ビット バージョンの Office 2010 ではオプションです。これにより、既存の Declare ステートメントは従来どおりに動作します。

次の表では、既に説明した新しい修飾子とデータ型について再度説明すると共に、もう 1 つのデータ型と 2 つの変換演算子と 3 つの関数についても説明します。

種類

アイテム

説明

修飾子

PtrSafe

Declare ステートメントが 64 ビットと互換性があることを示します。この属性は 64 ビット システムでは必須です。

データ型

LongPtr

変数のデータ型であり、Office 2010 の 32 ビット バージョンでは 4 バイトのデータ型で、64 ビット バージョンでは 8 バイトのデータ型です。これは新しいコードでポインターやハンドルを宣言するときの推奨方法です。ただし、レガシー コードでも、64 ビット バージョンの Office 2010 で実行する場合は、やはりこれが推奨される方法です。これは 32 ビットおよび 64 ビットで VBA 7 ランタイムでのみサポートされます。そこに数値を代入することはできますが、数値型を代入することはできません。

データ型

LongLong

これは 64 ビット バージョンの Office 2010 でのみ使用できる 8 バイトのデータ型です。数値を代入することはできますが、数値型を代入することはできません (切り詰められるのを避けるためです)。

変換演算子

CLngPtr

単純な式を LongPtr データ型に変換します。

変換演算子

CLngLng

単純な式を LongLong データ型に変換します。

関数

VarPtr

バリアント コンバーター。64 ビット バージョンでは LongPtr を返し、32 ビット バージョンでは Long を返します (4 バイト)。

関数

ObjPtr

オブジェクト コンバーター。64 ビット バージョンでは LongPtr を返し、32 ビット バージョンでは Long を返します (4 バイト)。

関数

StrPtr

文字列コンバーター。64 ビット バージョンでは LongPtr を返し、32 ビット バージョンでは Long を返します (4 バイト)。

次の例は、これらのアイテムのいくつかについて、Declare ステートメントでの使用方法を示したものです。

Declare PtrSafe Function RegOpenKeyA Lib "advapi32.dll" (ByVal Key As LongPtr, ByVal SubKey As String, NewKey As LongPtr) As Long

Declare ステートメントで PtrSafe を指定しないと、64 ビット バージョンの Office 2010 と互換性がないものと見なされます。

既に述べたように、VBA7Win64 という 2 つの新しい条件付きコンパイル定数があります。以前のバージョンの Microsoft Office との下位互換性を確保するには、VBA7 定数を使用して、以前のバージョンの Microsoft Office で 64 ビット コードが使用されないようにします (これがより一般的なやり方です)。32 ビット バージョンと 64 ビット バージョンとでコードが異なる場合は (たとえば、64 ビット バージョンについては LongLong を使用し、32 ビット バージョンについては Long を使用する数値演算 API を呼び出す場合など)、Win64 定数を使用します。次のコードで、この 2 つの定数の使用例を示します。

#if Win64 then
   Declare PtrSafe Function MyMathFunc Lib "User32" (ByVal N As LongLong) As LongLong
#else
   Declare Function MyMathFunc Lib "User32" (ByVal N As Long) As Long
#end if
#if VBA7 then
   Declare PtrSafe Sub MessageBeep Lib "User32" (ByVal N AS Long)
#else
   Declare Sub MessageBeep Lib "User32" (ByVal N AS Long)
#end if

要約すると次のようになります。64 ビットのコードを書き、それを以前のバージョンの Microsoft Office で使用する場合は、VBA7 条件付きコンパイル定数を使用する必要があります。しかし、32 ビットのコードを書き、それを Office 2010 で使用する場合は、このコンパイル定数を使用しなくても、そのコードは以前のバージョンの Microsoft Office での動作と同じになります。32 ビット バージョンには間違いなく 32 ビットのステートメントが使われ、64 ビット バージョンには間違いなく 64 ビットのステートメントが使われるようにするには、Win64 条件付きコンパイル定数を使用するのが最善策です。

次のコードは、更新する必要があるレガシー VBA コードの例です。このレガシー コードのデータ型に注目してください。これらはハンドルまたはポインターを参照しているので、LongPtr を使用するように更新する必要があります。

レガシー VBA コード

Declare Function SHBrowseForFolder Lib "shell32.dll" _
  Alias "SHBrowseForFolderA" (lpBrowseInfo As BROWSEINFO) As Long
  
Public Type BROWSEINFO
  hOwner As Long
  pidlRoot As Long
  pszDisplayName As String
  lpszTitle As String
  ulFlags As Long
  lpfn As Long
  lParam As Long
  iImage As Long
End Type

新しい VBA コード

#if VBA7 then    ' VBA7 
Declare PtrSafe Function SHBrowseForFolder Lib "shell32.dll" _
  Alias "SHBrowseForFolderA" (lpBrowseInfo As BROWSEINFO) As Long

Public Type BROWSEINFO
  hOwner As LongPtr
  pidlRoot As Long
  pszDisplayName As String
  lpszTitle As String
  ulFlags As Long
  lpfn As LongPtr
  lParam As LongPtr
  iImage As Long
End Type
 
#else    ' Downlevel when using previous version of VBA7

Declare Function SHBrowseForFolder Lib "shell32.dll" _
  Alias "SHBrowseForFolderA" (lpBrowseInfo As BROWSEINFO) As Long

Public Type BROWSEINFO
  hOwner As Long
  pidlRoot As Long
  pszDisplayName As String
  lpszTitle As String
  ulFlags As Long
  lpfn As Long
  lParam As Long
  iImage As Long
End Type
 
#end if
Sub TestSHBrowseForFolder ()
    Dim bInfo As BROWSEINFO
    Dim pidList As Long

    bInfo.pidlRoot = 0&
    bInfo.ulFlags = &H1
    pidList = SHBrowseForFolder(bInfo)
End Sub

32 ビット バージョンと 64 ビット バージョンの Microsoft Office に関連する、よく寄せられる質問を以下にまとめています。

どのような場合に 64 ビット バージョンの Microsoft Office を使用するのですか。

これは、使用しているホスト アプリケーション (Excel、Word など) に応じて異なります。たとえば、Excel は、64 ビット バージョンの Microsoft Office ではずっと大きなワークシートを処理できます。

64 ビット バージョンと 32 ビット バージョンの Microsoft Office を一緒にインストールできますか。

いいえ。

どのような場合に Long パラメーターをLongPtr に変換するのですか。

Microsoft Developers Network の Windows API のドキュメントで、呼び出す関数について確認する必要があります。ハンドルとポインターは LongPtr に変換する必要があります。例として、RegOpenKeyA の説明では以下のシグネチャを示しています。

LONG WINAPI RegOpenKeyEx(
  __in        HKEY hKey,
  __in_opt    LPCTSTR lpSubKey,
  __reserved  DWORD ulOptions,
  __in        REGSAM samDesired,
  __out       PHKEY phkResult
);

パラメーターは次のように定義されます。

パラメーター

説明

hKey [in]

レジストリ キーを開くハンドル

lpSubKey [in, optional]

開くレジストリ サブキーの名前。

ulOptions

このパラメーターは予約されており、ゼロにする必要があります。

samDesired [in]

キーに対する必要なアクセス権を指定するマスク。

phkResult [out]

開いたキーへのハンドルを受け取る変数へのポインター

Win32API_PtrSafe.txt では、Declare ステートメントが次のように定義されています。

Declare PtrSafe Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" (ByVal hKey As LongPtr, ByVal lpSubKey As String, ByVal ulOptions As Long, ByVal samDesired As Long, phkResult As LongPtr) As Long
構造体のポインターとハンドルを変換する必要がありますか。

はい。Win32API_PtrSafe.txt の MSG 型を参照してください。

Type MSG
    hwnd As LongPtr
    message As Long
    wParam As LongPtr
    lParam As LongPtr
    time As Long
    pt As POINTAPI
End TypeF
どのような場合に strptrvarpt、および objptr を使用するのですか。

これらの関数は、それぞれ文字列、変数、およびオブジェクトへのポインターを取得する場合に使用してください。64 ビット バージョンの Microsoft Office では、これらの関数は 64 ビットの LongPtr を返します。これは、Declare ステートメントに渡すことができます。これらの関数の使用法は、以前のバージョンの VBA から変更されていません。唯一の違いは、LongPtr を返すようになったことです。

64 ビット バージョンの Office 2010 が追加されたことにより、能力の向上に伴ってより多くのデータを移動させることができるようになりました。32 ビット コードを書く場合は、変更なしで 64 ビット バージョンの Microsoft Office を使用できます。しかし、64 ビット コードを書く場合は、そのコードに特定のキーワードと条件付きコンパイル定数を含めることで、以前のバーションの Microsoft Office との下位互換性が確保されるようにし、32 ビット コードと 64 ビット コードを組み合わせて使用する場合には正しいコードが実行されるように処置する必要があります。

Declare ステートメントの詳細については、次のリソースを参照してください。

表示: