Excel VBAのコーディング事例をご紹介しています。
事例のテーマを決めて、その機能を実現するためのコーディングを動く形でお示して行きます。
今回はコーディング事例は含まれていますがどちらかと言うとoffice製品のレジストリに関する話題になります。
「レジストリの話題」と言ってしまうと、とてつもなく広大な話になってしまうのですが今回はOffice製品が使用するTypeLibに関する話題に絞ってご紹介いたします。
なおコーディング自体は「構造化・標準化は考慮しつつも極力コーディング量は減らし、その上で可読性を維持する」という思いは持ちつつも「テーマに沿って動くことを優先して実装」しています。
32bit版Excel 2016の バージョン2201(ビルド 14827.20198)を使用して検証しています。
そもそもタイプライブラリとは
.NETクラスライブラリの台頭によりCOM(Component Object Model)自体は一昔前といいますか標準としての機能呼び出しの仕組みになっているので、タイプライブラリについてあまり存じ上げない方も多いことと思いますが、VBAにおいては外部コンポ―ネットを使用するする上では欠かせない機能になります。
COMの詳細な説明につきましては下記のMicrosoft Docsのページをご参照ください。
COMコンポーネント(オブジェクト)はVBAのオブジェクトブラウザー(Visual Basic for Applicationの「表示」メニュから選択)ではクラスとして表示されているのですが、クラスのメンバーとしてFunction(メソッド)やProperty(プロパティ)が定義されています。
これらはCOMの機能を呼び出すためのインターフェース定義でありこれらをVBAで実装するためにはプログラマがメソッドを実行するためのコードを自分で記述する必要があります。
つまり単機能以外はCOMコンポーネント(オブジェクト)を呼び出しただけで機能を実装できる訳ではありません。
インターフェースの説明につきましては下記のMicrosoft Docsのページをご参照ください。
以上を踏まえVBAでCOMコンポーネント(オブジェクト)を使うためにはCOMコンポーネント(オブジェクト)が使用しているプログラミング言語とVBAの間を橋渡しする必要があるのですが、その役割を担っているのがタイプライブラリになります。
詳しい説明は下記のMicrosoft Docsのページをご参照ください。
タイプライブラリには、クラス、インターフェイス、列挙など、1つまたは複数の COM 要素の仕様が含まれていますが、ライブラリファイル自体は「標準のバイナリ形式」であり、拡張子「.tlb」の単独のタイプライブラリファイルにするか、または「.ocx/.dll/.exe」拡張子の実行可能ファイルの中に含めた形にすることができます。
そして「Microsoftの開発製品には、タイプライブラリ情報の生成、抽出、および表示に使用できるツールが用意されている」のですが、VBAの場合は「オブジェクトブラウザー(Visual Basic for Applicationの「表示」メニュから選択)」になりますが、表示のみで生成・抽出の機能はありません。
なお表示させるためにはVisual Basic for Applicationの「ツール」メニュ→「参照設定」で対象のタイプライブラリのチェックボックスをオンにする必要があります。
上記の原典は下記のMicrosoft Docsページです。
タイプライブラリのレジストリ エントリ
タイプライブラリの前にCOMコンポーネント(オブジェクト)のクラスに関してレジストリに登録されている情報を確認してみます。
COMコンポーネント(オブジェクト)のクラスはCLSIDというグローバル識別子を持っていますが、これはつぎのレジストリ エントリに登録されているのですが、このことは下記のMicrosoft Docsのページに記載されています。
\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
なおこのページの注釈にはつぎのようなことが書かれています。
HKEY_LOCAL_MACHINE\SOFTWARE\Classesキーは、以前のバージョンのCOMとの互換性のために保持されたHKEY_CLASSES_ROOTキーに対応しています。
ただしこの記述だけでは詳細が解らないので下記のMicrosoft Docsのページも併せて参照いたします。
HKEY_LOCAL_MACHINE\Software\Classesキーには、ローカル コンピューター上のすべてのユーザーに適用できる既定の設定が含まれています。 HKEY_CURRENT_USER\Software \Classesキーには、対話型ユーザーにのみ適用される設定が含まれています。 HKEY_ CLASSES_ROOTキーは、これら2つのソースの情報をマージするレジストリのビューを提供します。HKEY_CLASSES_ROOTは、旧バージョンのWindows用に設計されたアプリケーションに対してマージされたビューを提供します。
「対話型ユーザにのみ適用される設定」の意味を理解できていませんが、このドキュメントを見る限りHKEY_CLASSES_ROOTキーを使った方が良さそうです。
ところで話をタイプライブラリに戻しますが、実はタイプライブラリに関してはMicrosoft Docsで検索してもレジストリ エントリについて書かれたドキュメントを見つけることができませんでした。
でもHKEY_LOCAL_MACHINE\SOFTWARE\Classesキーの直下にはTypeLibというフォルダがあり、更にその直下には「中かっこのペア内の 128 ビットの数値 (16 進数)」 のキーが300~400個存在していて、それをブレイクダウンして行くとファイルパスのデータがあり、それらのファイルの拡張子の多くが「.tlb/.ocx/.dll/.exe」などになっているので、これがタイプライブラリであると推察いたします。
そうは言ってもこの記述だけでは信憑性に欠けるのでVBAでTypeLibの情報を新しいワークシートに書き出すためのコーディング事例をご紹介いたします。
TypeLibレジストリデータを取得するコーティング事例
レジストリ データは、WMI(Windows Management Instrumentation)のStdRegProvクラスとそのメソッドを使用して取得する事ができます。
コーディング例はMicrosoft Docsの下記ページにも掲載されていますが、そのままでは動かない箇所もあるので、TypeLibに特化して今回必要な情報を新しいワークシートに書き出すコーディング事例をご紹介いたします。
Sub TypeLibPrint() Dim obj_Reg As Object Dim v_key1 As Variant, v_key2 As Variant, v_key3 As Variant, v_key4 As Variant Dim i1 As Integer, i2 As Integer, i3 As Integer, i4 As Integer, iRow As Integer, idx As Integer Dim st_wk As String Dim st_result As String '対象キー Dim l_hkey As Long, st_key As String Const HKEY_CLASSES_ROOT As Long = &H80000000 Const HKEY_LOCAL_MACHINE As Long = &H80000002 Const REG_KEY1 As String = "TypeLib" Const REG_KEY2 As String = "SOFTWARE\Classes\TypeLib" Const SHEETNAME As String = "TypeLib." idx = 1 '1の時はHKEY_CLASSES_ROOT、以外はHKEY_LOCAL_MACHINE If idx = 1 Then l_hkey = HKEY_CLASSES_ROOT st_key = REG_KEY1 Else l_hkey = HKEY_LOCAL_MACHINE st_key = REG_KEY2 End If Set obj_Reg = GetObject("winmgmts:\\Localhost\root\default:StdRegProv") st_wk = st_key Call GetKeys(obj_Reg, l_hkey, st_wk, v_key1) '戻り値はv_key?(?は整数)に配列で返る iRow = 0 Application.ScreenUpdating = False '画面固定 With addNewSheet(SHEETNAME & idx) '新しいシートを指定の名前で追加 '階層化されたレジストリ情報を取得 For i1 = 0 To UBound(v_key1) st_wk = st_key & "\" & v_key1(i1) If GetKeys(obj_Reg, l_hkey, st_wk, v_key2) Then For i2 = 0 To UBound(v_key2) st_wk = st_key & "\" & v_key1(i1) & "\" & v_key2(i2) '第4パラメータが空文字の時は"既定"データを取得 st_result = GetValue(obj_Reg, l_hkey, st_wk, "") If GetKeys(obj_Reg, l_hkey, st_wk, v_key3) Then For i3 = 0 To UBound(v_key3) st_wk = st_key & "\" & v_key1(i1) & "\" & v_key2(i2) & "\" & _ v_key3(i3) If GetKeys(obj_Reg, l_hkey, st_wk, v_key4) Then For i4 = 0 To UBound(v_key4) st_wk = st_key & "\" & v_key1(i1) & "\" & v_key2(i2) & "\" & _ v_key3(i3) & "\" & v_key4(i4) '読み込まれたデータをNEXT行の1~6カラムに書込み iRow = iRow + 1 .Cells(iRow, 1).Value = i1 + 1 .Cells(iRow, 2).Value = v_key1(i1) .Cells(iRow, 3).Value = v_key2(i2) .Cells(iRow, 4).Value = v_key4(i4) .Cells(iRow, 5).Value = st_result .Cells(iRow, 6).Value = GetValue(obj_Reg, l_hkey, st_wk, "") Next i4 End If Next i3 End If Next i2 End If Next i1 Cells.Select '入力範囲を選択 Cells.EntireColumn.AutoFit '列の幅を自動調整 .Cells(1, 1).Select 'A1セルを選択して範囲選択を解消 End With Application.ScreenUpdating = True '画面固定解除 Set obj_Reg = Nothing End Sub
Private Function GetKeys(oReg As Object, lhkey As Long, stKey As String, ByRef SubKeys As Variant) As Boolean GetKeys = False oReg.EnumKey lhkey, stKey, SubKeys If IsArray(SubKeys) Then GetKeys = True End Function
Private Function GetValue(oReg As Object, lhkey As Long, stKey As String, sVal As String) As String oReg.GetStringValue lhkey, stKey, sVal, GetValue End Function
※シート オブジェクトを返すaddNewsheetファンクションを2023/1/29追記しました。
Public Function addNewSheet(stSheetName As String) As Object Set addNewSheet = Sheets.Add(after:=Sheets(Sheets.Count)) '新しいシートを追加 addNewSheet.Name = stSheetName 'シート名を変更 End Function
以下に簡単ではありますが仕様をリストアップいたします。
- メインとなるサブルーチン「TypeLibPrint」と、サブキーを取得する「GetKeys」とサブキーのデータを取得する「GetValue」という2つのファンクションで構成されています。
- 14行目で変数idxに「1」を指定した時は、前章でご説明したHKEY_CLASSES_ROOTキーのTypeLibを対象にします。
「1」以外の整数を指定した時はHKEY_LOCAL_MACHINE\SOFTWARE\ClassesキーのTypeLibを対象にします。 - それぞれ「”TypeLib.” & idx」というシート名で新しいシートを追加して書き出します。
- 出力する項目は下記になります。
- 連番(ライブラリごと)
- タイプライブラリのID
- 128 ビットの数値 (16 進数)
- サブキー:バージョン
- サブキー:win32/win64
- 「サブキー:バージョン」の既定データでタイプライブラリの名称
- 名称がセットされていないライブラリも存在します。
- 「サブキー:win32/win64」の既定データでタイプライブラリのファイルパス
- ファイルパスの後に「\整数」が付いている場合があります。
TypeLibにどれくらいの数のライブラリが登録されているか?は端末にインストールしているアプリケーションによって変わってくるので、コーディングを実行すると何行くらい出力されるかは一概には言えませんが弊社パソコンではライブラリの数は400弱で出力行数は600行弱になりました。
なお両者の違いは、複数バージョンでの登録やwin32とwin64でのダブルで登録があるライブラリが存在する事によります。
Officeのタイプライブラリのレジストリ エントリ
前段が長くなってしまいましたが、ここでようやく本題に入ります。
前章で書き出されたTypeLibの中身を確認していて「HKEY_LOCAL_MACHINE\SOFTWARE\ClassesキーのTypeLibの中にはOffice関連のタイプライブラリが含まれていないものがある」という点に気が付きました。
例えばVBAの本体である「Visual Basic For Applications」は存在しているのですが、ファイルパスを見ると「C:\Windows\SysWOW64\msvbvm60.dll」になっていて、このdllは「Visual Basic 6.0ランタイムライブラリ」であって最新のものではありません。英語表記になりますが下記Microsoft Docsのページにmsvbvm60.dllがwindows10でのサポート対象になっていることが書かれています。
ではOfficeで使用されているTypeLibはどこにレジストリ エントリがあるのでしょうか?
この話に入る前に2点ほど確認しなければならない点があるのでそちらを先にご説明いたします。
冒頭でご紹介しているように弊社のOffice環境は32bit版Excel 2016の バージョン2201(ビルド 14827.20198)で、しかもパソコン購入時にオプション購入したバンドル製品です。
確認するのは①32ビット版である事、②バンドル製品である事と言いますかインストール方式に関しての2点で、Office 2016である点については今回は影響がないと判断いたします。
①32ビット版Officeである事の影響
そもそも64ビットのWindows OSで32ビット版のOfficeを動かすためにはWOW64(Microsoft Windows-32-on-Windows-64)サブシステムを使用するのですが、これにより利用する側は意識する事なく32ビットプロセッサーのアーキテクチャであるx86やARMで動かすためのアプリケーションを64ビットアーキテクチャであるx64やARM64の上でシームレスに実行することができるようになります。
ただしWOW64を使用して動いている32ビット版のOfficeからCOMコンポーネント(オブジェクト)を呼び出す場合には、COMは32ビットで動かせるように作られている必要があります。
言い換えますとWOW64が64ビットでしか動かない(32 ビット バイナリと互換性がない)ように作られているCOMを32ビット版のOfficeから呼び出せるようにしてくれる訳ではありません。
詳細は下記2つのMicrosoft Docsのページをご参照ください。
つぎに32ビットプログラムが「どこのレジストリ エントリを参照するのか?」についてのポイントをリストアップいたします。
- 32ビットプログラムが32ビット用に64ビットキーとは異なるキーを持つ場合
- 64 ビット 版のレジストリ エディターではHKEY_LOCAL_MACHINE\Software\WOW6432Nodeに表示されます。
- 32ビットプログラムが32ビットキーと64ビットキーで同じ名前を持つ場合
- 64ビットキーと同じレジストリ エントリHKEY_LOCAL_MACHINE\Softwareに両者が表示されます。
詳細は下記Microsoft Docsのページをご参照ください。
では32ビット版のOfficeはどうなるのか?と言うとレジストリ エディターの内容を見る限りOffice製品としては”2″にあたる認識です。
ただしOfficeの中にある32ビット機能は”1″の結果を返すものがあるようです。
詳細は後段でご説明いたします。
②Office 2016のインストール方式によるレジストリ エントリの違い
インストール方式ですがOffice 2016までは「クイック実行形式(Click-To-Run:C2R)」と「Windowsインストーラー形式(MSI)」の両方が併存していました。
下記のVisual Studio フォーラムのページをご参照ください。
なおOffice 2019以降のインストール方式はクイック実行形式(C2R)だけになっているため、MSIの場合のレジストリ エントリについては簡単にポイントをリストアップした上で取得のためのコーディング事例をご紹介いたします。
弊社パソコンでのMSIの場合のOffice TypeLibのレジストリ エントリは下記のようになっています。
- \HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PackagedCom\Package
(\HKEY_CLASSES_ROOT\PackagedCom\Packageでも同じ)- Microsoft.Office.Desktop_16051.14931.20132.0_x86__8wekyb3d8bbwe\TypeLib
- Office全般
- Microsoft.Office.Desktop.Excel_16051.14931.20132.0_x86__8wekyb3d8bbwe\TypeLib
- Excel固有
- その他のOffice製品については省略いたします。
- Microsoft.Office.Desktop_16051.14931.20132.0_x86__8wekyb3d8bbwe\TypeLib
MSIの場合は「Classes\PackagedCom\Package\パッケージ名」の直下にTypeLibが存在していました。
なおパッケージ名の”16051″はインストール時のバージョン番号、”14931.20132″は現時点でのビルド番号、その後の”8wekyb3d8bbwe”はWindows10のパッケージ名に付けられている(固定の)識別コードになる認識です。
現時点でのビルド番号が付いているという事は、Officeのバージョンが更新されるごとにこのキーの配下は書き換えられている事になります。
MSIの場合のOfficeタイプライブラリを取得するためのコーディング事例
コーディングの仕様は先ほどとほぼ同じで違うのはキーの数と、win32/win64のレジストリ上での設定の仕方の違いによります。またキーを取得する「GetKeys」とサブキーのデータを取得する「GetValue」という2つのファンクションは先ほどと同じなのでここでは省略しています。
Office全般とExcel個別のどちらを対象にするか?のフラグは16行目の変数idxに1または2をセットすることで指定します。
なおMSIの場合には理由は判りませんがタイプライブラリの名称がレジストリデータとしてはどこにも保存されていないようです。
ではVBAの参照設定に表示される「参照可能なライブラリ ファイル」の名称はどこから取得しているのか?疑問ではありますが追跡できていませんのでお含み置きください。
Sub registryPackage() Dim obj_Reg As Object Dim v_key1 As Variant, v_key2 As Variant Dim i1 As Integer, i2 As Integer, idx As Integer, iRow As Integer Dim st_wk As String, st_32 As String, st_64 As String Dim REG_KEY(1 To 2) As String Const WIN32 As String = "win32", WIN64 As String = "win64" Const SHEETNAME As String = "TypeLib1." '対象キー Const HKEY_CLASSES_ROOT As Long = &H80000000 Const WIN32PATH As String = "win32Path", WIN64PATH As String = "win64Path" REG_KEY(1) = "PackagedCom\Package\Microsoft.Office.Desktop.Excel_" & _ "16051.14931.20132.0_x86__8wekyb3d8bbwe\TypeLib" REG_KEY(2) = "PackagedCom\Package\Microsoft.Office.Desktop_16051." & _ "14931.20132.0_x86__8wekyb3d8bbwe\TypeLib" idx = 2 '1の時はExcel固有、2の時はOffice全般 Set obj_Reg = GetObject("winmgmts:\\Localhost\root\default:StdRegProv") st_wk = REG_KEY(idx) '戻り値はv_key?(?は整数)に配列で返る If GetKeys(obj_Reg, HKEY_CLASSES_ROOT, st_wk, v_key1) = False Then Exit Sub '<<<<<<<< End If iRow = 0 With addNewSheet(SHEETNAME & idx) '新しいシートを指定の名前で追加 '階層化されたレジストリ情報を取得 For i1 = 0 To UBound(v_key1) iRow = iRow + 1 st_wk = REG_KEY(idx) & "\" & v_key1(i1) If GetKeys(obj_Reg, HKEY_CLASSES_ROOT, st_wk, v_key2) Then For i2 = 0 To UBound(v_key2) '読み込まれたデータをNEXT行の1~5カラムに書込み .Cells(iRow, 1).Value = i1 + 1 .Cells(iRow, 2).Value = v_key1(i1) st_wk = REG_KEY(idx) & "\" & v_key1(i1) & "\" & v_key2(i2) .Cells(iRow, 3).Value = v_key2(i2) st_32 = GetValue(obj_Reg, HKEY_CLASSES_ROOT, st_wk, WIN32PATH) st_64 = GetValue(obj_Reg, HKEY_CLASSES_ROOT, st_wk, WIN64PATH) If st_32 <> "" And st_64 = "" Then .Cells(iRow, 4).Value = WIN32 .Cells(iRow, 5).Value = st_32 ElseIf st_32 = "" And st_64 <> "" Then .Cells(iRow, 4).Value = WIN64 .Cells(iRow, 5).Value = st_64 ElseIf st_32 <> "" And st_64 <> "" Then .Cells(iRow, 4).Value = WIN32 .Cells(iRow, 5).Value = st_32 iRow = iRow + 1 .Cells(iRow, 1).Value = i1 + 1 .Cells(iRow, 2).Value = v_key1(i1) .Cells(iRow, 3).Value = v_key2(i2) .Cells(iRow, 4).Value = WIN64 .Cells(iRow, 5).Value = st_64 End If If i2 <> UBound(v_key2) Then iRow = iRow + 1 Next i2 End If Next i1 Cells.Select '入力範囲を選択 Cells.EntireColumn.AutoFit '列の幅を自動調整 .Cells(1, 1).Select 'A1セルを選択して範囲選択を解消 End With Set obj_Reg = Nothing End Sub
次の章でOffice TypeLibの具体的な内容についてご説明いたします。
インストール方式がクイック実行形式(C2R)の場合のレジストリ エントリ
Officeで使用されているTypeLibは探すべき情報が判っていれば検索をする事で見つける事ができます。
今回は「Visual Basic For Applications」の文字列で検索をしますが、先の章でご説明したTypeLibにも存在しているので、先ほどとは異なる場所にあるTypeLibにぶら下がっている情報を見つけ出します。
もしかするとパソコンの環境によってはWOW6432\TypeLibでも検出されるかもしれませんが、それはスルーしてください。
すると次のキーが検出される事と存じます。
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\ClickToRun\REGISTRY\MACHINE\Software\Classes\TypeLib
そこで先の章でご紹介したWMI(Windows Management Instrumentation)のStdRegProvクラスとそのメソッドを使用したコーディング事例を使ってTypeLibの中身をリストアップしようとしても何も値は戻ってきません。
この原因は先の章でご説明いたしました「①32ビット版Officeである事の影響」によるものと推察いたします。
この理由は試しにキーを「HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office」に変えてコーディング事例を実行して調べてみると「HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Office」の内容を書き出そうとします。
がしかしWOW6432Nodeの配下にはClickToRunのサブキーが存在しないために何も値を返さないのです。
これは推測になりますが、WMI(Windows Management Instrumentation)の機能は32ビットプログラムであるためにそのメソッドはWOW6432Nodeの方を参照してしまうのではないでしょうか?
そうなると先の章でタイプリブの階層を「\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\TypeLib」にしていましたが、「\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Classes\TypeLib」にしなければならないはずです。
ただしそう思って弊社パソコンで両者を確認したところLibidの数は目視で数えると一緒であり、ザックリ見た範囲で内容的にも違いは無さそうでした。
そのためコーディングはそのままにしていますのでお含み置きください。(結果はリダイレクトされるためにWOW6432Nodeの内容を書き出すことになりますが…)
なおレジストリキーの条件はWOW6432Nodeした方が勘違いは無くなることと存じます。
Const REG_KEY1 As String = "WOW6432Node\TypeLib" Const REG_KEY2 As String = "SOFTWARE\WOW6432Node\Classes\TypeLib"
以上の結果を受けてやむなく今回はレジスト エディタで上記ClickToRun配下のTypeLibをエクスポートして中身を加工してリストアップしました。
なお下記ExcelシートはMicrosoftサポートの「OneDrive から Web ページやブログに Excel ブックを埋め込む」に基づきOneDrive「https://onedrive.live.com」にアクセスして表示しています。※iframeを使用しています。
ちなみに弊社のパソコン環境では67個のタイプライブラリが登録されています。
リストアップしている項目は下記のようになります。
カラム | 項目 | 内容 |
---|---|---|
1 | No | タイプライブラリに付番した連番 |
2 | Name | タイプライブラリの名称 |
3 | Libid | タイプライブラリのIDで128 ビットの数値 (16 進数) |
4 | Ver | タイプライブラリのバージョン |
5 | OS | win32 または win64のサブキー |
6 | Path | ClickToRun\…\TypeLibに登録されているパス |
7 | c | PathとClassesPathの値が異なる時は「X」。等しい時は空文字 |
8 | ClassesPath | HKEY_CLASSES_ROOT\TypeLibに登録されているパス |
8カラム目のClassesPathはHKEY_CLASSES_ROOT\TypeLibに同じLibidを持つデータがあった場合に、そのPath情報をリストアップしています。
8カラム目にデータが存在するタイプライブラリの数は67個の内の22個になりますが、残りの45個はOfficeのTypeLibにしか登録されていないタイプライブラリになります。
ただしこの45個のタイプライブラリの内にVBAコーディングでよく使われるタイプライブラリがあるか?と言われると、正直使わないものがほとんどであると思います。
言い換えるとOffice製品の中で特殊用途に使用されているタイプライブラリになっているようです。
なぜHKEY_CLASSES_ROOT\TypeLibとOfficeのタイプライブラリに同じLibidのものが存在するのか?
両方に存在する22個のタイプライブラリの内、登録されているパスまで一緒なのは13個で残り9個はパスが異なっているものが含まれています。
パスが同じものは詮索する事は難しいので、パスが異なる8個について考えてみたいと思います。
上記のワークシートは先ほどのワークシートからパスが異なるライブラリだけにしてTibidを取り除きPathとClassesPathを2段表示にする加工をしています。
背景色が付いている方がOfficeタイプリブのPathになります。
茶色の外枠を付けたNo1、15、24はPathの異なり方が他と比べて特殊です。
- No1.Visual Basic for Applications
- OfficeのPathは現時点、ClassesPathはVB6のモジュールを指している。
- No15.Microsoft Forms 2.0 Object Library(VBAでユーザフォームを挿入すると自動的に参照設定されるタイプライブラリ)
- OfficeのPathはVB6、ClassesPathは現時点のモジュールを指している。
- No24.Microsoft OneNote 15.0 Extended Type Library(OneNoteを操作する時に使用する)
- win64のClassesPathだけ異なるモジュールを指している。
なので、一旦これらは置いておいて残りの6個を比べて見ます。
すると次の2つのパターンになる事が判ります。
- No10、64のパターン
- OfficeのPath”Program Files”(青色)がClassesPathでは
“Program Files (x86)\Microsoft Office\root\VFS\ProgramFilesX64″(赤色)に
- OfficeのPath”Program Files”(青色)がClassesPathでは
- No6、23、28、40のパターン
- OfficeのPath”Common Files”(青色)がClassesPathでは”Microsoft Office\Root\VFS\ProgramFilesCommonX86″(赤色)に
最近のOfficeのバージョン格納されるフォルダーの階層が深くなる傾向があるので、この結果を見ると「OfficeのPathには古いバージョンのPathが残っていだけでは?」と思われるかもしれません。
実際にエクスプローラでファイルを探してみると青色のOfficeのパスを見つける事ができませんでした。
ただ、理由は判りませんがこのパスをVBAのDIR関数で調べてみると空文字ではなくファイル名が戻されます。
下記にレジストリに登録されているファイルパスの存在を確認するコーディング事例をご紹介いたします。
Public Function fileExistchk(stFilename As String) As String Dim st_wk As String Dim iPos As Integer If stFilename = "" Then fileExistchk = "" Exit Function '<<<<<<<< End If fileExistchk = "False" iPos = InStrRev(stFilename, Chr(92)) st_wk = Mid(stFilename, iPos + 1) If IsNumeric(st_wk) Then stFilename = Left(stFilename, iPos - 1) If stFilename = "" Then fileExistchk = "" ElseIf Dir(stFilename) <> "" Then fileExistchk = "True" End If End Function
11行目でファイルパスの最後に「\整数」が付与されていた場合、「\整数」を取り除いています。
結局両者に同じLibidのライブラリが存在する理由は、Microsoftが仕様を公開してくれないとハッキリとは解りませんが、恐らく「古いバージョンに対応するための仕組み」が関係しているように思います。
最後に
今回Officeのタイプライブラリのレジストリ エントリを探す事になったそもそもの理由は、『VBAのツールメニューの参照設定に表示されている数多くの「参照可能なライブラリ ファイル」が何の情報に基づくのか?』を調べている時にHKEY_CLASSES_ROOT\TypeLibに登録されていないタイプライブラリが存在する事に気付いたためです。
ご説明いたしましたように結果としてOfficeのタイプライブラリには「Visual Basic For Applications」以外はOffice製品の中で特殊用途に使用されているものが多く含まれているようです。
そのためわざわざ掘り下げなくても良かったのかもしれませんが、ただ今回いろいろとレジストリの中身を調べる事で「何で同じキーがいろいろなところで出現するのか?」という疑問のいくつかは解消する事ができたので何かしら皆様のお役に立てる点があれば幸いです。
なお「結局VBAではOfficeのタイプライブラリを取得できないのですか?」という疑問が生じる事と存じますが、現時点でWMI(Windows Management Instrumentation)がwin32 APIである事は間違いありません。(Windowsアプリ開発のページではデスクトップWin32アプリの配下のWindows Serverの下にWMIの項目が存在します)
そうなるとWMIが32ビット版ではなく、64ビット版にならないと取得するのは難しいかもしれません。
以上最後までご一読いただき誠にありがとうございました。