thom氏のブログで面白い記事がありました。
・VBA 参照設定でライブラリを探すのが面倒なので、ライブラリを検索できる参照設定ダイアログを自作してみた – t-hom’s diary
http://thom.hateblo.jp/entry/2016/02/10/235414
VBEの参照設定ダイアログが使いづらいので自分で作ってしまおう、というお話しです。
そう、thom氏の言う通り、参照設定ダイアログは“使いづらい”です。イケてないです。
私も常々そう思っていました。
(ならもっと前から何か工夫しておこうよ・・・って話なのですが、それをやらないのが私です。)
thom氏の記事にはコードも載っていて、それを見るとUserFormに配置したListBox等のコントロールを使って、ライブラリの検索や参照を行うようです。
素晴らしい。
これは便利そう!
・・・ならばパクるしかない!!
UserFormを用意することすら面倒くさい
というわけで、私も似たような「自作参照ダイアログ」をやってみることにしたのですが、そこは不精な私、UserFormを用意してコントロールを配置することすら面倒くさい、そう感じてしまいます。
なので、下記のようにCommandBarComboBoxを使って必要最低限のUIのみで処理を実現することにしました。
・処理概要
- レジストリからTypeLib情報を取得し、XMLファイルに格納する。
- CommandBarを作成し、ComboBoxを追加する。
- XMLから読み込んだTypeLib情報をComboBoxに放り込む。
- ComboBoxで選択したライブラリを参照設定する。
アドインのコード
実際に書いたコードが下記になります。
ソートのためにRecordsetオブジェクトを使ったりしていますが、そう複雑なことはやっていません。
'ThisWorkbook Option Explicit Private Const XmlFileName As String = "TypeLibInfo.xml" Private Const CbarName As String = "TypeLib" Private Const CboCaption As String = "TypeLibBox" Private WithEvents Btn As Office.CommandBarButton Private Sub Workbook_Open() Init End Sub Private Sub Workbook_AddinInstall() Init End Sub Private Sub Workbook_AddinUninstall() On Error Resume Next Application.VBE.CommandBars(CbarName).Delete On Error GoTo 0 End Sub Private Sub Init() Dim Cbar As Office.CommandBar Dim Cbo As Office.CommandBarComboBox Dim d As Object Dim nodes As Object Dim XmlFilePath As String Dim i As Long On Error Resume Next Set Cbar = Application.VBE.CommandBars(CbarName) If Err.Number <> 0 Then Select Case Err.Number Case 1004 MsgBox "[セキュリティ センターの設定]から" & vbNewLine & vbNewLine & _ "【VBA プロジェクト オブジェクト モデルへのアクセスを信頼する】" & vbNewLine & vbNewLine & _ "にチェックを入れた後、アドインを再度読み込んでください。", vbExclamation + vbSystemModal Exit Sub End Select Err.Clear End If On Error GoTo 0 If Cbar Is Nothing Then 'コマンドバー設定 Set Cbar = Application.VBE.CommandBars.Add(Name:=CbarName, Position:=msoBarFloating) Set Cbo = Cbar.Controls.Add(Type:=msoControlComboBox) Cbo.Caption = CboCaption Cbo.Width = 150 Set Btn = Cbar.Controls.Add(Type:=msoControlButton) Btn.Caption = "参照" Btn.Style = msoButtonCaption 'XMLファイル読込 XmlFilePath = AddPathSeparator(ThisWorkbook.Path) & XmlFileName With CreateObject("Scripting.FileSystemObject") If .FileExists(XmlFilePath) = False Then CreateTypeLibXml XmlFilePath End If End With Set d = CreateObject("Msxml2.DOMDocument") If d.Load(XmlFilePath) = True Then Set nodes = d.SelectNodes("/items/item") For i = 0 To nodes.Length - 1 Cbo.AddItem nodes.item(i).Attributes(1).Text, i + 1 Next End If End If Cbar.Visible = True End Sub Private Sub Btn_Click(ByVal Ctrl As Office.CommandBarButton, CancelDefault As Boolean) Dim d As Object Dim XmlFilePath As String With Application.VBE.CommandBars(CbarName).Controls(CboCaption) If .ListIndex > 0 Then Set d = CreateObject("Msxml2.DOMDocument") XmlFilePath = AddPathSeparator(ThisWorkbook.Path) & XmlFileName If d.Load(XmlFilePath) = True Then 'MsgBox d.SelectNodes("/items/item").item(.ListIndex - 1).Attributes(2).Text '確認用 On Error Resume Next Application.VBE.ActiveVBProject.References.AddFromFile _ d.SelectNodes("/items/item").item(.ListIndex - 1).Attributes(2).Text If Err.Number <> 0 Then MsgBox "参照設定に失敗しました。", _ vbCritical + vbSystemModal, _ "Error No:" & Err.Number Err.Clear End If On Error GoTo 0 End If End If End With End Sub Private Sub CreateTypeLibXml(ByVal XmlFilePath As String) 'TypeLib情報をXMLに格納 Dim reg As Object Dim rs As Object Dim d As Object Dim item As Object Dim items As Object Dim names As Variant Dim child_names As Variant Dim lib As Variant Dim tlb As Variant Dim ret1 As Long, ret2 As Long Dim i As Long, j As Long Const adVarChar = 200 Const HKEY_CLASSES_ROOT = &H80000000 Const SubKeyName As String = "TypeLib" 'レジストリから取得したTypeLib情報をRecordsetに格納 Set reg = CreateObject("WbemScripting.SWbemLocator") _ .ConnectServer(, "root\default") _ .Get("StdRegProv") reg.EnumKey HKEY_CLASSES_ROOT, SubKeyName, names If Not IsNull(names) Then Set rs = CreateObject("ADODB.Recordset") rs.Fields.Append "GUID", adVarChar, 255 rs.Fields.Append "Name", adVarChar, 255 rs.Fields.Append "Library", adVarChar, 255 rs.Open For i = LBound(names) To UBound(names) reg.EnumKey HKEY_CLASSES_ROOT, SubKeyName & ChrW(92) & names(i), child_names If Not IsNull(child_names) Then For j = LBound(child_names) To UBound(child_names) ret1 = reg.GetStringValue(HKEY_CLASSES_ROOT, _ SubKeyName & ChrW(92) & _ names(i) & ChrW(92) & _ child_names(j), _ "", _ lib) ret2 = reg.GetStringValue(HKEY_CLASSES_ROOT, _ SubKeyName & ChrW(92) & _ names(i) & ChrW(92) & _ child_names(j) & ChrW(92) & _ "0" & ChrW(92) & _ "win32", _ "", _ tlb) If (ret1 = 0) And (ret2 = 0) Then rs.AddNew rs.Fields("GUID").Value = names(i) rs.Fields("Name").Value = lib rs.Fields("Library").Value = tlb rs.Update End If Next End If Next rs.Sort = "Name ASC" '名前順でソート 'TypeLib情報をXMLファイルとして保存 rs.MoveFirst Set d = CreateObject("Msxml2.DOMDocument") Set items = d.createElement("items") Do Until rs.EOF Set item = d.createElement("item") item.setAttribute "guid", rs.Fields("GUID").Value item.setAttribute "name", rs.Fields("Name").Value item.setAttribute "library", rs.Fields("Library").Value items.appendChild item Set item = Nothing rs.MoveNext Loop rs.Close d.appendChild items On Error Resume Next d.Save XmlFilePath If Err.Number <> 0 Then MsgBox "XMLファイルの保存に失敗しました。" & vbNewLine & _ XmlFilePath, vbCritical + vbSystemModal Err.Clear End If On Error GoTo 0 End If End Sub Private Function AddPathSeparator(ByVal str As String) As String If Right(str, 1) <> ChrW(92) Then str = str & ChrW(92) AddPathSeparator = str End Function
動作画面
実際にアドインを読み込んで、動作させたときの様子が下図になります。
ComboBoxとCommandButtonしかシンプルなインターフェースで、自分で使った感じでは、なかなか使いやすいです。
ダウンロード
コードは上に書いていますが、一応アドインファイルもアップしておきますので、興味がある方は試してみてください。
(「VBA プロジェクト オブジェクト モデルへのアクセスを信頼する」にチェックが入っていないと使用できませんので、その点はご注意ください。)
► ダウンロード
この記事へのコメントはありません。