概要 — 完全商用レベルの「Excel UI デザイナー」設計方針
企業で使えるレベルの UI デザイナーは、ただコントロールを並べるだけでなく、再利用可能なコンポーネント、テーマ/スタイル管理、コード自動生成、バージョン管理、エクスポート(テンプレ)/ インポート、セキュリティ対策、テスト支援、ユーザー向けドキュメント生成 まで含めます。
以下は「設計方針」「主要機能一覧」「実装テンプレ(VBAコード+使い方)」「運用上の注意点」をステップバイステップで示した完全テンプレです。すぐコピペで使えるコア実装(主要部のみ)を含みます。
主要機能(商用レベル要件)
- デザインキャンバス(ドラッグ&ドロップで配置/移動/リサイズ)
- コントロールパレット(ラベル、テキストボックス、ボタン、ComboBox, ListBox, ProgressBar, Calendar など)
- プロパティエディタ(選択コントロールのプロパティをツリー/表形式で編集)
- レイアウト補助(グリッド、スナップ、整列、等間隔分布)
- テーマ管理(カラー・フォント・角丸・影などをテンプレ化)
- コード自動生成(Initialize / ControlEvents / 保存/復元コード)
- コンポーネントライブラリ(再利用可能な UserControl 風のクラス)
- プロジェクト管理(複数フォーム/バージョン管理/エクスポート)
- リボン連携(リボンにツールを追加)
- セキュリティと配布(署名、Trust Access、配布手順)
- テスト自動化ヘルパー(ダミーデータ注入、ロードテスト)
- ドキュメント/サンプルの自動生成
アーキテクチャ(モジュール分割)
- UserForm:
frmDesigner(メインのデザインUI) - UserForm:
frmProperty(プロパティエディタ) - UserForm:
frmPalette(コントロールパレット) - Module:
modBuilder(UI生成・コード注入ロジック) - Module:
modProject(プロジェクト管理/保存・読み込み) - Class:
clsControlModel(設計上のコントロール抽象モデル) - Class:
clsComponent(再利用コンポーネント) - Module:
modRibbon(リボン登録ヘルパ) - Module:
modUtil(汎用関数、APIラッパー)
必須設定(導入時に注意)
- VBA エディタの「ツール」→「参照設定」で Microsoft Forms 2.0 Object Library を有効にする(通常は参照済)。
- 「開発」→「マクロのセキュリティ」または Excel のセキュリティ設定で Trust access to the VBA project object model を有効にする(コードでVBProjectを操作するため必須)。
- 配布時は署名・デジタル証明の検討/使用者向け手順(上記を許可してもらう)を用意する。
操作フロー(ユーザー視点)
frmDesignerを起動。左にfrmPalette(パーツ)、中央がキャンバス、右がfrmProperty。- パレットからコントロールをドラッグしてキャンバスにドロップ(もしくはクリックで追加)。
- コントロールを選択:プロパティエディタで Caption/Name/サイズ/位置/タグ/データバインドなど編集。
- グリッドにスナップさせ、整列・配列ボタンで見た目を整える。
- 「Generate」ボタンで UserForm と、必要な初期化コード・イベントスタブを自動生成。
- 生成フォームをプロジェクトに追加して、編集・テスト・エクスポート(テンプレ)を行う。
実装テンプレ:最小限稼働するコア(コピーして使えるコード)
※ ここでは「コア機能」を短く示します。商用化する場合は例外処理・ログ・権限チェック・大規模な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
VBfrmPalette(コントロールパレット) — 単純な追加ボタン
' UserForm: frmPalette
' CommandButtons: btnLabel, btnTextBox, btnButton
Private Sub btnLabel_Click()
' パレットから追加(実際はドラッグ座標が必要)
frmDesigner.cmdNewControl_Click
End Sub
VBfrmProperty(プロパティ編集) — 単純なプロパティ表示/編集(モデル)
' 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
VBmodBuilder(コード注入:キャンバスから 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
VBfrmDesigner 側でキャンバス内の各コントロールに 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 アドインでラッパーを作る(上級)。 - 簡易実装:ユーザーに「ファイル」→「オプション」→「クイックアクセスツールバー」へ
マクロを追加してもらう手順書を同梱すると配布が楽。
配布・導入手順(運用上のチェックリスト)
- Excel ファイルを
.xlsmで配布。配布物に「導入手順 (PDF)」を付属。 - 「Trust access to the VBA project object model」の許可方法を明記。
- 署名(デジタル証明書)でマクロがブロックされないようにする(企業環境ならIT部門と調整)。
- バージョン管理:
_metaシートにバージョン番号・変更履歴を記載。 - テストケース(手順書)を同梱。
品質保証/テスト戦略
- ユニット:モジュール単位で動作確認(コード生成、保存/読み込み)。
- 結合:生成フォームを実際にロードしてイベント発火まで確認。
- 回帰:既存テンプレートを上書き生成しても動作するか自動チェック。
- UI テスト:主要操作(ドラッグ、リサイズ、プロパティ編集、Generate)を手順化して実行。
セキュリティ・注意点
- ユーザー環境で
Trust access to the VBA project object modelを有効にする必要があるため、権限問題・情報漏洩リスクを文書で説明すること。 - 自動生成コードは必ずバックアップ/差分を取る。上書きで業務ロジックを壊すと大事故。
- パスワードや機密情報をフォームにハードコーディングしない(Secure Vault の利用等を検討)。
追加で用意できる商用機能(提案)
- ビジュアルテンプレマーケット:組織内で使うテンプレを GUI で追加・管理。
- 翻訳/ローカライズ支援(多言語プロパティ)。
- 分散チーム向けのテンプレ同期(SharePoint / OneDrive 経由)。
- GUI テスト自動化ツールとの連携(VBA 単体での自動テストを補助)。
- エクスポート機能:生成フォームを
xlam/dotx相当のテンプレ形式で配布。
サンプル導入手順(今すぐ動かすミニガイド)
- 新規 Excel ブックを作成し、開発タブを有効にする。
- VBA エディタで標準モジュール
modBuilder、UserFormfrmDesigner、frmPalette、frmPropertyを作る。上の「実装テンプレ」を各所へコピー。 - 参照設定で
Microsoft Visual Basic for Applications ExtensibilityとMicrosoft Scripting Runtimeを有効にする。 - Excel のオプションで「Trust access to the VBA project object model」を有効にする。
frmDesignerを実行して、cmdNewControlやcmdGenerateを試す。- 生成されたフォーム(例:GeneratedForm1)がプロジェクトに追加されているか確認する。


