和風スパゲティのレシピ

日本語でコーディングするExcelVBA

ActiveXボタンをフォームボタンに置換するマクロ

Excel2024からActiveXコントロールが使用できなくなりました。

ActiveXコントロール

理由が「セキュリティの脆弱性」であるため、
Excel365も追従する可能性が高いです。


新規に挿入することはもちろんできなくなりますが、
既存のコントロールも選択や押下ができなくなり、
そこに設置したマクロ(イベント)も実行できなくなります。


この問題に対応するための、
アクティブシートの全ActiveXボタンを一括でフォームボタンに置き換えるマクロ
を紹介します。


ActiveXから置き換わったフォームボタン
↑こんな感じで、同じ位置/同じ大きさ/同じマクロをセットした、
「元_ボタン名」というフォームボタンを生成
します。



実行型の便利マクロですので、
Excel起動時に裏で開かれる「個人用マクロブック」などに搭載して使ってください。


と言いつつこのマクロはある程度作業が終われば不要になるものなので、
普通のブックに書いておき、使い終わったら押し入れにしまうくらいがちょうどいいかもしれません。

ソースコード

Sub アクティブシートのActiveXコントロールボタンをフォームコントロールボタンに置き換える()
    
    Dim 対象シート As Worksheet: Set 対象シート = ActiveSheet
    
    ' ActiveXコントロールのうちCommandButtonだけを処理
    Dim OLEオブジェクト As OLEObject
    For Each OLEオブジェクト In 対象シート.OLEObjects
        If TypeName(OLEオブジェクト.Object) = "CommandButton" Then
        
            ' 位置・サイズ・キャプション(テキスト)・マクロ名を取得
            Dim ボタンtop As Double, ボタンleft As Double
            Dim ボタンwidth As Double, ボタンheight As Double
            Dim ボタンテキスト As String, ボタン名 As String, マクロ名 As String
            With OLEオブジェクト
                ボタンtop = .Top
                ボタンleft = .Left
                ボタンwidth = .Width
                ボタンheight = .Height
                ボタンテキスト = .Object.Caption
                ボタン名 = .Name
                マクロ名 = 対象シート.CodeName & "." & .Name & "_Click"
            End With
            
            ' 同じ位置に同じ大きさでフォームコントロールのボタンを挿入
            Dim フォームボタン As Button
            Set フォームボタン = 対象シート.Buttons.Add( _
                Top:=ボタンtop, Left:=ボタンleft, _
                Width:=ボタンwidth, Height:=ボタンheight)
            
            ' ActiveXボタンの設定を追加したフォームボタンに反映
            With フォームボタン
                .Name = "元_" & ボタン名
                .Caption = ボタンテキスト
                .OnAction = マクロ名
            End With
            
            ' ActiveXボタンを削除
            OLEオブジェクト.Delete
            
        End If
    Next ' ActiveXコントロールのうちCommandButtonだけを処理
    
    MsgBox "すべてのActiveXボタンの置き換えを完了しました。"

End Sub

解説

↓以下の処理を愚直に実行している割とストレートなコードです。

  1. シート内のActiveXコントロール(OLEオブジェクト)をFor Eachループ
  2. 位置や大きさ、名称、設定マクロ名などを記憶
  3. それらを反映させたフォームボタンを挿入
  4. 完了後にActiveXのボタンを削除

一つ一つの処理は複雑なことはしていませんので、
コメントと変数名を読めば処理の流れはつかめると思います。


仕様上の注意点として、両ボタンにセットするマクロは通常

  • ActiveXボタン:ボタン名称に「_Click」を付けたイベントプロシージャ
  • フォームボタン:任意のマクロを手作業で設置(どこに書いてもOK)

という違いがあります。


今回はActiveXにセットされたマクロをフォームボタンに付け替えるのですが、
「シートモジュール上のPrivateプロシージャは、
 シートオブジェクト名.プロシージャ名 でボタンに設置可能」

という小技を使って設定しています。


Privateプロシージャは通常マクロの一覧には表示されず
故にボタンにセットすることは出来なそうに感じるのですが、

Privateプロシージャをボタンに設置

↑このように「シートオブジェクト名.マクロ名」を手入力することで、
リストにないPrivateプロシージャでもボタンに登録することが可能になります。


この技はもちろん「OnAction」への設定でも使用できますので、
今回のコードでもこの仕様を活用しています。


なお、この設定にはシート名ではなくシートオブジェクト名を使う必要があり、
Worksheet.CodeNameで取得していることに留意してください。

シートオブジェクト名についてはこちらの記事をどうぞ

www.limecode.jp


最後に注意として、
ActiveXにおいてボタン名とマクロ名が必ず一致しているとは限りません。

加えてActiveXコントロールの設定イベントも正確に取得することはできませんので、
このマクロで置き換えたボタン達は必ず動作確認をお願いします。