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 単体での自動テストを補助)。
  • エクスポート機能:生成フォームを xlamdotx 相当のテンプレ形式で配布。

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

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