VBA コンボボックスにフォントリストを表示

フォームにフォントリストを表示するコンボボックスを作ってみました。


フォームにコンボボックスを追加し、クリックします。

Private Sub ComboBox1_Change()が作成されるので、右側のプロシージャープルダウンから、DropButtonClickを選択します。


すると、Private Sub ComboBox1_DropButtonClick()プロシージャーが作成されます。これは、ドロップボタンがクリックされたときに実行されます。

作成されたプロシージャーに次のように入力します。

コピペ用:

Private Sub ComboBox1_DropButtonClick()
    Dim uCB As CommandBarComboBox
    Dim i As Long
    
    If ComboBox1.ListCount = 0 Then
        Set uCB = Application.CommandBars.FindControl(ID:=1728)
        With uCB
            For i = 1 To .ListCount
                ComboBox1.AddItem .List(i)
            Next
        End With
    End If
End Sub


標準モジュールを追加して、次のようにフォームを表示するプロシージャーを作り、実行します。

次のようにフォームが表示され、ドロップボタンをクリックするとフォントリストが表示されます。


職場でWord上で実装した際には、クリックしてからリストが表示されるまでに、2、3秒かかりました。

自宅でExcel上で実行したところ、ほぼ瞬時でした。WordとExcelの違いか、マシンパワーの違いか、はたまたセキュリティ対策ソフトの違いか。

いずれにしろ、Word上では、フォームの初期化時にフォントリストを作成すると、フォームが表示されるのが遅かったので、とりあえずフォームを表示し、ドロップボタンをクリックされたときに作成されるようにしました。


参考

基本的な考え方はこちらに書かれています。

フォントの一覧を取得する Office TANAKA

IDを使ってコントロールを特定する方法がこちらです。

[ExcelVBA] フォントの一覧を取得

フォントファイルを検索して、それをリストするという方法もヒットしましたが、それだと並び順が良く使うフォント順にならないと思い、上記の方法を採用しました。

ただ、サイトによっては、このコマンドバーを使う方法はサポートされていないとも書かれているので、将来の互換性が怪しいかもしれません。


コード解説

一応コードの解説をしておこうと思います。

Private Sub ComboBox1_DropButtonClick()
    Dim uCB As CommandBarComboBox
    Dim i As Long
    
    If ComboBox1.ListCount = 0 Then
        Set uCB = Application.CommandBars.FindControl(ID:=1728)
        With uCB
            For i = 1 To .ListCount
                ComboBox1.AddItem .List(i)
            Next
        End With
    End If
End Sub

全体としては、Officeのメニューにあるフォントのコンボボックスから、ユーザーフォームのコンボボックスに、フォント名をコピーするというものです。

はじめの If ComboBox1.ListCount = 0 Then はフォントを二回以上読み込むのを防ぐためのものです。自宅環境ではほぼ瞬時ですが、職場のPCでは遅かったためです。

Set uCB = Application.CommandBars.FindControl(ID:=1728) は、ID 1728のコントロールをコマンドバーから探して、取得するというものです。ID 1728がフォントリストのコンボボックスに相当するようです。

コマンドバーは昔のOfficeのユーザーインターフェイスで、現在はリボンインターフェイスに置き換えられています。互換性のために今のところは使えるのではないかと思います。

For i = 1 To .ListCount は、コンボボックスのアイテム(フォント名)の数だけ、iをカウントアップしています。 .ListCountは コンボボックスのアイテム数を示しています。

ComboBox1.AddItem .List(i) は、カウントアップするiを使って、Listのアイテム(フォント名)を取得し、ユーザーフォームのコンボボックスに追加しています。

この部分、Listがリスト構造なら、 for each uItem in .List で高速化できるのではと思いました(リスト構造にインデックスを使ってアクセスすると遅い)。しかし、試してみるとエラーが発生し、 .List は指定できませんでした。

また、 List() の引数 Indexは必須のパラメーターでした。

CommandBarComboBox.List property (Office)

そして、デバッグのためローカルウィンドウで uCBの中身を見たところ、なんと List プロパティは表示されませんでした。

一応 uCB. と打つと List は表示され、インテリセンスは効いています。

CommandBarComboBoxのListは奇妙な実装です。

追記: パラメーター必須のプロパティはローカルウィンドウに表示されないそうです。

VBEの使い方:ローカル ウィンドウ


コメント

アクセス数の多い投稿

セキュリティ対策ソフトのノートンが詐欺ソフトまがいになってしまってショック

ZIPファイルを開こうとすると、展開を完了できません、と言われる

Excel 2019 クエリが原因で日本語入力の一文字目が勝手に確定する

オカムラ家具のOAチェアー、コンテッサを分解清掃

突然滅茶苦茶遅くなったPCがWindows Updateのキャッシュクリアで復活

Excelのテーブルに行や列を挿入する際のエラー

ChatGPTが日本語からVBAのコードを生成できてたまげる

Windows セキュリティーのビックリマークが消えない

Power Automate Desktopでブラウザでダウンロードしたファイルを処理する

Excel VBAからODBCを使ってデータを簡単に取得する