Excel VBA | 完全商用レベルの UI デザイナー化

Excel VBA VBA
スポンサーリンク
スポンサーリンク

概要 — 完全商用レベルの「Excel UI デザイナー」設計方針

企業で使えるレベルの UI デザイナーは、ただコントロールを並べるだけでなく、再利用可能なコンポーネント、テーマ/スタイル管理、コード自動生成、バージョン管理、エクスポート(テンプレ)/ インポート、セキュリティ対策、テスト支援、ユーザー向けドキュメント生成 まで含めます。
以下は「設計方針」「主要機能一覧」「実装テンプレ(VBAコード+使い方)」「運用上の注意点」をステップバイステップで示した完全テンプレです。すぐコピペで使えるコア実装(主要部のみ)を含みます。


主要機能(商用レベル要件)

  1. デザインキャンバス(ドラッグ&ドロップで配置/移動/リサイズ)
  2. コントロールパレット(ラベル、テキストボックス、ボタン、ComboBox, ListBox, ProgressBar, Calendar など)
  3. プロパティエディタ(選択コントロールのプロパティをツリー/表形式で編集)
  4. レイアウト補助(グリッド、スナップ、整列、等間隔分布)
  5. テーマ管理(カラー・フォント・角丸・影などをテンプレ化)
  6. コード自動生成(Initialize / ControlEvents / 保存/復元コード)
  7. コンポーネントライブラリ(再利用可能な UserControl 風のクラス)
  8. プロジェクト管理(複数フォーム/バージョン管理/エクスポート)
  9. リボン連携(リボンにツールを追加)
  10. セキュリティと配布(署名、Trust Access、配布手順)
  11. テスト自動化ヘルパー(ダミーデータ注入、ロードテスト)
  12. ドキュメント/サンプルの自動生成

アーキテクチャ(モジュール分割)

  • UserForm: frmDesigner(メインのデザインUI)
  • UserForm: frmProperty(プロパティエディタ)
  • UserForm: frmPalette(コントロールパレット)
  • Module: modBuilder(UI生成・コード注入ロジック)
  • Module: modProject(プロジェクト管理/保存・読み込み)
  • Class: clsControlModel(設計上のコントロール抽象モデル)
  • Class: clsComponent(再利用コンポーネント)
  • Module: modRibbon(リボン登録ヘルパ)
  • Module: modUtil(汎用関数、APIラッパー)

必須設定(導入時に注意)

  1. VBA エディタの「ツール」→「参照設定」で Microsoft Forms 2.0 Object Library を有効にする(通常は参照済)。
  2. 「開発」→「マクロのセキュリティ」または Excel のセキュリティ設定で Trust access to the VBA project object model を有効にする(コードでVBProjectを操作するため必須)。
  3. 配布時は署名・デジタル証明の検討/使用者向け手順(上記を許可してもらう)を用意する。

操作フロー(ユーザー視点)

  1. frmDesigner を起動。左に frmPalette(パーツ)、中央がキャンバス、右が frmProperty。
  2. パレットからコントロールをドラッグしてキャンバスにドロップ(もしくはクリックで追加)。
  3. コントロールを選択:プロパティエディタで Caption/Name/サイズ/位置/タグ/データバインドなど編集。
  4. グリッドにスナップさせ、整列・配列ボタンで見た目を整える。
  5. 「Generate」ボタンで UserForm と、必要な初期化コード・イベントスタブを自動生成。
  6. 生成フォームをプロジェクトに追加して、編集・テスト・エクスポート(テンプレ)を行う。

実装テンプレ:最小限稼働するコア(コピーして使えるコード)

※ ここでは「コア機能」を短く示します。商用化する場合は例外処理・ログ・権限チェック・大規模なUI改善が必要です。

frmDesigner(メインフォーム) — 概要と主要イベント

' UserForm: frmDesigner
' - Frame: fraCanvas  (キャンバス)
' - CommandButton: cmdGenerate
' - CommandButton: cmdNewControl
' - Label: lblStatus

Private Sub UserForm_Initialize()
    ' 初期化:グリッドサイズ等
    Me.lblStatus.Caption = "Ready"
    Call frmPalette.Show      ' パレットを表示(モードはモードレス)
    Call frmProperty.Show
End Sub

Private Sub cmdNewControl_Click()
    ' サンプル:クリックでラベルをキャンバスに追加(実際はドラッグで座標を取得)
    Dim ctl As MSForms.Label
    Set ctl = Me.fraCanvas.Controls.Add("Forms.Label.1", "lbl_" & Format(Now, "hhmmss"), True)
    With ctl
        .Caption = "NewLabel"
        .Left = 10
        .Top = 10
        .Width = 80
        .Height = 18
    End With
    Call SelectControlOnCanvas(ctl.Name)
End Sub

Public Sub SelectControlOnCanvas(ctrlName As String)
    ' 選択コントロールをプロパティパネルに通知
    frmProperty.LoadProperties Me.fraCanvas.Controls(ctrlName)
    Me.lblStatus.Caption = "Selected: " & ctrlName
End Sub

Private Sub cmdGenerate_Click()
    ' 生成トリガー:選択コントロール情報を集めてコード生成
    Call modBuilder.BuildFormFromCanvas(Me, "GeneratedForm1")
    MsgBox "フォームを生成しました: GeneratedForm1"
End Sub
VB

frmPalette(コントロールパレット) — 単純な追加ボタン

' UserForm: frmPalette
' CommandButtons: btnLabel, btnTextBox, btnButton

Private Sub btnLabel_Click()
    ' パレットから追加(実際はドラッグ座標が必要)
    frmDesigner.cmdNewControl_Click
End Sub
VB

frmProperty(プロパティ編集) — 単純なプロパティ表示/編集(モデル)

' UserForm: frmProperty
' Controls: txtName, txtCaption, txtLeft, txtTop, cmdApply

Public currentControl As MSForms.Control

Public Sub LoadProperties(c As MSForms.Control)
    Set currentControl = c
    Me.txtName.Value = c.Name
    Me.txtCaption.Value = IIf(TypeName(c) = "Label", c.Caption, "")
    Me.txtLeft.Value = c.Left
    Me.txtTop.Value = c.Top
End Sub

Private Sub cmdApply_Click()
    If currentControl Is Nothing Then Exit Sub
    currentControl.Name = Me.txtName.Value
    If TypeName(currentControl) = "Label" Then currentControl.Caption = Me.txtCaption.Value
    currentControl.Left = Val(Me.txtLeft.Value)
    currentControl.Top = Val(Me.txtTop.Value)
End Sub
VB

modBuilder(コード注入:キャンバスから UserForm 生成のコア)

' Module: modBuilder
Option Explicit

Public Sub BuildFormFromCanvas(designer As Object, newFormName As String)
    ' 1) 新しい UserForm を作成
    Dim vbComp As VBIDE.VBComponent
    Set vbComp = ThisWorkbook.VBProject.VBComponents.Add(vbext_ct_MSForm)
    vbComp.Name = newFormName
    
    ' 2) 生成したフォームにキャンバス上のコントロールを複製
    Dim ctrl As MSForms.Control
    Dim dest As MSForms.UserForm
    Set dest = vbComp.Designer
    
    For Each ctrl In designer.fraCanvas.Controls
        Dim newCtl As MSForms.Control
        Select Case TypeName(ctrl)
            Case "Label"
                Set newCtl = dest.Controls.Add("Forms.Label.1", ctrl.Name, True)
                newCtl.Caption = ctrl.Caption
            Case "TextBox"
                Set newCtl = dest.Controls.Add("Forms.TextBox.1", ctrl.Name, True)
            Case "CommandButton"
                Set newCtl = dest.Controls.Add("Forms.CommandButton.1", ctrl.Name, True)
            Case Else
                ' 必要に応じて追加
        End Select
        
        If Not newCtl Is Nothing Then
            newCtl.Left = ctrl.Left
            newCtl.Top = ctrl.Top
            newCtl.Width = ctrl.Width
            newCtl.Height = ctrl.Height
        End If
    Next
    
    ' 3) ベーシックなコード(Initialize とイベントスタブ)をモジュールに追加
    Dim codeMod As VBIDE.CodeModule
    Set codeMod = vbComp.CodeModule
    Dim startLine As Long
    startLine = codeMod.CountOfLines + 1
    
    codeMod.InsertLines startLine, "Private Sub UserForm_Initialize()" & vbCrLf & _
                                 "    ' 自動生成された初期化コード" & vbCrLf & _
                                 "End Sub"
    
    ' 4) 各ボタンのクリックイベントスタブを作る(例)
    ' ここでは Label にはイベント不要。CommandButton があればスタブを作る
    Dim i As Long
    For Each ctrl In designer.fraCanvas.Controls
        If TypeName(ctrl) = "CommandButton" Then
            startLine = codeMod.CountOfLines + 1
            codeMod.InsertLines startLine, "Private Sub " & ctrl.Name & "_Click()" & vbCrLf & _
                                             "    ' TODO: 実装" & vbCrLf & _
                                             "End Sub"
        End If
    Next
End Sub
VB

注意:上記コードは Microsoft Visual Basic for Applications Extensibility 参照を必要とします(VBE オブジェクト操作)。


拡張:ドラッグ&ドロップ/移動・リサイズの実装方針

UserForm 上での本格的なドラッグ&ドロップを実装するには、キャンバスを Frame にして、その中でコントロールの MouseDown/MouseMove/MouseUp をハンドルします。各コントロールに共通の MouseHandler を割り当てるには WithEvents を用いたクラスラッパ(例:clsDraggable)を使います。

簡単な clsDraggable のイメージ:

' Class: clsDraggable
Public WithEvents ctl As MSForms.Control
Private dragging As Boolean
Private startX As Single, startY As Single, origLeft As Single, origTop As Single

Private Sub ctl_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    dragging = True
    startX = X: startY = Y
    origLeft = ctl.Left: origTop = ctl.Top
End Sub

Private Sub ctl_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    If dragging Then
        ctl.Left = origLeft + (X - startX)
        ctl.Top = origTop + (Y - startY)
    End If
End Sub

Private Sub ctl_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    dragging = False
End Sub
VB

frmDesigner 側でキャンバス内の各コントロールに clsDraggable インスタンスを関連付けることでドラッグが動きます。


テーマ・コンポーネント化(クラスベース)

clsComponent を用意して、プロパティ(Caption, Font, BackColor, Padding, Behavior)を保持。テンプレ化してライブラリへ保存/読み込みできるようにします。保存形式は JSON 風の text にするか、Hidden シートに保存しておくと配布・移植に便利です。

' Class: clsComponent
Public Name As String
Public TypeName As String
Public Props As Scripting.Dictionary   ' Requires Microsoft Scripting Runtime

Public Sub Initialize()
    Set Props = New Scripting.Dictionary
End Sub
VB

コード自動注入(高度)

  • イベントコードを自動で記述する際は、テンプレートエンジン(文字列組み立て)を使い、重複チェックと既存コード保護を行う。
  • 生成前に VBComponent.CodeModule の既存コードをバックアップ(ファイル保存)する仕組みを必ず入れる。
  • 生成後は Lint チェック(簡易)と Unit Test(フォームロード・簡易イベント呼び出し)を実行する。

リボン連携(配布容易化)

  • Office Ribbon XML を利用してアドイン的にリボンボタンを追加。VBA からは CustomUI を含む xlsm を作るか、COM アドインでラッパーを作る(上級)。
  • 簡易実装:ユーザーに「ファイル」→「オプション」→「クイックアクセスツールバー」へ マクロ を追加してもらう手順書を同梱すると配布が楽。

配布・導入手順(運用上のチェックリスト)

  1. Excel ファイルを .xlsm で配布。配布物に「導入手順 (PDF)」を付属。
  2. 「Trust access to the VBA project object model」の許可方法を明記。
  3. 署名(デジタル証明書)でマクロがブロックされないようにする(企業環境ならIT部門と調整)。
  4. バージョン管理:_meta シートにバージョン番号・変更履歴を記載。
  5. テストケース(手順書)を同梱。

品質保証/テスト戦略

  • ユニット:モジュール単位で動作確認(コード生成、保存/読み込み)。
  • 結合:生成フォームを実際にロードしてイベント発火まで確認。
  • 回帰:既存テンプレートを上書き生成しても動作するか自動チェック。
  • UI テスト:主要操作(ドラッグ、リサイズ、プロパティ編集、Generate)を手順化して実行。

セキュリティ・注意点

  • ユーザー環境で Trust access to the VBA project object model を有効にする必要があるため、権限問題・情報漏洩リスクを文書で説明すること。
  • 自動生成コードは必ずバックアップ/差分を取る。上書きで業務ロジックを壊すと大事故。
  • パスワードや機密情報をフォームにハードコーディングしない(Secure Vault の利用等を検討)。

追加で用意できる商用機能(提案)

  • ビジュアルテンプレマーケット:組織内で使うテンプレを GUI で追加・管理。
  • 翻訳/ローカライズ支援(多言語プロパティ)。
  • 分散チーム向けのテンプレ同期(SharePoint / OneDrive 経由)。
  • GUI テスト自動化ツールとの連携(VBA 単体での自動テストを補助)。
  • エクスポート機能:生成フォームを xlam/dotx 相当のテンプレ形式で配布。

サンプル導入手順(今すぐ動かすミニガイド)

  1. 新規 Excel ブックを作成し、開発タブを有効にする。
  2. VBA エディタで標準モジュール modBuilder、UserForm frmDesigner、frmPalette、frmProperty を作る。上の「実装テンプレ」を各所へコピー。
  3. 参照設定で Microsoft Visual Basic for Applications Extensibility と Microsoft Scripting Runtime を有効にする。
  4. Excel のオプションで「Trust access to the VBA project object model」を有効にする。
  5. frmDesigner を実行して、cmdNewControl や cmdGenerate を試す。
  6. 生成されたフォーム(例:GeneratedForm1)がプロジェクトに追加されているか確認する。
タイトルとURLをコピーしました