- プロレベル VBA 演習 20問:模範解答+詳細解説
- 問題 1:リアルタイム入力監視フォーム
- 問題 2:多ブック連携マクロ
- 問題 3:外部 CSV / JSON 読み込みクラス化
- 問題 4:ADO+SQL Server 接続マクロ
- 問題 5:カスタムイベント+クラスモジュール
- ✅ まとめ(1〜5 問)
- 問題 6:VBAによるグラフ自動生成&カスタマイズ
- 問題 7:条件付き書式自動生成
- 問題 8:階層構造のツリービュー管理
- 問題 9:独自関数ライブラリ作成
- 問題 10:自動メール送信+添付ファイル管理
- ✅ まとめ(問題 6〜10)
- 問題 11:ブック間依存関係の解析
- 問題 12:大規模データの分割書き出し
- 問題 13:動的ピボットテーブル生成
- 問題 14:高度な文字列抽出・正規化
- 問題 15:API 連携(Web / JSON データ取得)
- ✅ まとめ(問題 11〜15)
- 問題 16:多階層ログ管理システム
- 問題 17:ユーザーフォーム + ListBox + 動的検索
- 問題 18:ブック自動バックアップ
- 問題 19:プロジェクト内コード自動生成
- 問題 20:統計・分析自動化
- ✅ まとめ(問題 16〜20)
プロレベル VBA 演習 20問:模範解答+詳細解説
ここからは プロレベル 20問の模範解答+詳細解説 を順番に紹介します。
さすがに 20問分は非常に長くなるので、まず 問題 1〜5 の模範解答+解説 を作り、
その後 6〜10 → 11〜15 → 16〜20 と分けて順次作成する形で進めます。
問題 1:リアルタイム入力監視フォーム
模範解答
ユーザーフォームの設計
- テキストボックス
txtInput - ラベル
lblMessage
コード例(UserForm モジュール)
Private Sub txtInput_Change()
Dim txt As String
txt = txtInput.Text
'文字数制限: 10文字以内
If Len(txt) > 10 Then
txtInput.Text = Left(txt, 10)
txtInput.SelStart = 10
lblMessage.Caption = "10文字までです"
lblMessage.ForeColor = vbRed
Else
lblMessage.Caption = "入力OK"
lblMessage.ForeColor = vbGreen
End If
End Sub
VB解説
Changeイベントで入力のたびに監視LeftとSelStartでカーソル位置を維持- Sub 分割例:
ValidateInput→ 文字数チェック・整形UpdateMessage→ ラベル更新
ポイント:イベント駆動 + 入力補正 + Sub 分割設計は、ユーザーフォームの基本かつ必須。
問題 2:多ブック連携マクロ
模範解答
Sub MergeWorkbooks()
Dim folderPath As String
Dim fileName As String
Dim wb As Workbook, destWb As Workbook
Dim ws As Worksheet
Dim lastRow As Long, pasteRow As Long
folderPath = "C:\Data\" '統合フォルダ
Set destWb = ThisWorkbook
pasteRow = 2
fileName = Dir(folderPath & "*.xls*")
Do While fileName <> ""
On Error GoTo SkipFile
Set wb = Workbooks.Open(folderPath & fileName)
Set ws = wb.Sheets(1)
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
ws.Range("A2:Z" & lastRow).Copy destWb.Sheets(1).Cells(pasteRow, 1)
pasteRow = pasteRow + lastRow - 1
wb.Close False
SkipFile:
fileName = Dir()
On Error GoTo 0
Loop
End Sub
VB解説
Dirでフォルダ内のブックを順番に取得On Error GoTo SkipFileで破損ファイルや開けないファイルをスキップ- コピー先の行番号は
pasteRowで管理 - ポイント:大規模データでも安全に統合できる設計
問題 3:外部 CSV / JSON 読み込みクラス化
模範解答(CSV の例)
'Class Module: clsData
Public DataArray() As String
Public Sub LoadCsv(filePath As String)
Dim f As Integer, line As String, tmp() As String
f = FreeFile
Open filePath For Input As #f
Dim i As Long: i = 0
Do Until EOF(f)
Line Input #f, line
tmp = Split(line, ",")
ReDim Preserve DataArray(i)
DataArray(i) = Join(tmp, "|") '内部で配列を文字列に変換して格納
i = i + 1
Loop
Close #f
End Sub
VB'標準モジュール
Sub TestCsvClass()
Dim obj As New clsData
obj.LoadCsv "C:\Data\sample.csv"
MsgBox "行数: " & UBound(obj.DataArray) + 1
End Sub
VB解説
- クラス化の利点:データの管理・加工・参照をまとめて扱える
- CSV → 配列 → クラスに格納 → 必要時に加工
- JSON の場合は
ScriptControlかVBA-JSONを使用
問題 4:ADO+SQL Server 接続マクロ
模範解答
Sub GetDataFromSQL()
Dim conn As Object, rs As Object
Dim sql As String
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets(1)
Set conn = CreateObject("ADODB.Connection")
conn.Open "Provider=SQLOLEDB;Data Source=SERVER;Initial Catalog=DB;User ID=USER;Password=PWD;"
sql = "SELECT TOP 10 * FROM Sales"
Set rs = conn.Execute(sql)
ws.Range("A1").CopyFromRecordset rs
rs.Close
conn.Close
Set rs = Nothing
Set conn = Nothing
End Sub
VB解説
ADODB.Connectionで SQL Server 接続CopyFromRecordsetで Excel に直接貼り付け- ポイント:接続→取得→解放の流れを必ずセットで記述
- エラー処理を追加するとプロ仕様
問題 5:カスタムイベント+クラスモジュール
模範解答
クラスモジュール:clsObservable
Public Event DataChanged(ByVal value As Variant)
Private mValue As Variant
Public Property Let Value(val As Variant)
mValue = val
RaiseEvent DataChanged(mValue)
End Property
Public Property Get Value() As Variant
Value = mValue
End Property
VB標準モジュール
Dim obj As clsObservable
Sub TestEvent()
Set obj = New clsObservable
'イベントハンドラをセット
With obj
'イベントハンドラを利用する場合は WithEvents で宣言した変数を UserForm や Class で扱う
.Value = 100 '値をセットするとイベントが発生
End With
End Sub
VB解説
RaiseEventで値変更を通知- 他の Sub でイベントハンドリング可能
- ポイント:データ駆動型設計(Observer パターン)を VBA で実装
✅ まとめ(1〜5 問)
- 問題 1:ユーザーフォーム + Change イベント
- 問題 2:多ブック統合 + エラー処理
- 問題 3:CSV/JSON クラス化
- 問題 4:ADO SQL Server 接続
- 問題 5:クラスモジュール + カスタムイベント
ここまでで基礎〜応用+設計力までのプロレベルが体験できる内容です。
問題 6:VBAによるグラフ自動生成&カスタマイズ
模範解答
Sub CreateChart()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets(1)
Dim chartObj As ChartObject
Set chartObj = ws.ChartObjects.Add(Left:=300, Width:=400, Top:=50, Height:=250)
With chartObj.Chart
.ChartType = xlColumnClustered
.SetSourceData Source:=ws.Range("A1:B6")
.HasTitle = True
.ChartTitle.Text = "売上グラフ"
.Axes(xlCategory).HasTitle = True
.Axes(xlCategory).AxisTitle.Text = "商品"
.Axes(xlValue).HasTitle = True
.Axes(xlValue).AxisTitle.Text = "売上"
.SeriesCollection(1).Format.Fill.ForeColor.RGB = RGB(0, 112, 192)
End With
End Sub
VB解説
ChartObjects.Addでシートにグラフを追加SetSourceDataで範囲を指定- タイトル・軸ラベル・色など細かく設定
- ポイント:自動生成+カスタマイズを Sub でまとめると再利用性高
問題 7:条件付き書式自動生成
模範解答
Sub AutoConditionalFormat()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets(1)
'クリア
ws.Cells.FormatConditions.Delete
'数値 > 1000 赤文字
ws.Range("B2:B100").FormatConditions.Add Type:=xlCellValue, Operator:=xlGreater, Formula1:="1000"
ws.Range("B2:B100").FormatConditions(ws.Range("B2:B100").FormatConditions.Count).Font.Color = vbRed
'文字列に "完了" が含まれる 緑背景
ws.Range("C2:C100").FormatConditions.Add Type:=xlTextString, String:="完了", TextOperator:=xlContains
ws.Range("C2:C100").FormatConditions(ws.Range("C2:C100").FormatConditions.Count).Interior.Color = vbGreen
End Sub
VB解説
FormatConditions.Addで条件を追加xlCellValue/xlTextStringなどで条件指定- ポイント:大量データで自動化すると手作業ゼロで書式設定可能
問題 8:階層構造のツリービュー管理
模範解答(ListBoxで代用)
Sub DisplayHierarchy()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets(1)
Dim lastRow As Long
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
Dim i As Long
Dim id As String, parent As String, name As String
Dim indent As String
For i = 2 To lastRow
id = ws.Cells(i, 1).Value
parent = ws.Cells(i, 2).Value
name = ws.Cells(i, 3).Value
indent = String(Len(parent) * 2, " ")
Debug.Print indent & name
Next i
End Sub
VB解説
String(n, " ")で階層深さに応じたインデント- ListBox / TreeView に置き換え可能
- ポイント:親子関係データを再帰的に処理する力がプロ仕様
問題 9:独自関数ライブラリ作成
模範解答
'標準モジュール modUtils
Public Function IsEven(n As Long) As Boolean
IsEven = (n Mod 2 = 0)
End Function
Public Function SafeDivide(a As Double, b As Double) As Double
If b = 0 Then
SafeDivide = 0
Else
SafeDivide = a / b
End If
End Function
VBSub TestUtils()
MsgBox "4は偶数? " & IsEven(4)
MsgBox "10 ÷ 0 = " & SafeDivide(10, 0)
End Sub
VB解説
- 独自関数をモジュール化すると 再利用性が向上
- エラー処理(ゼロ除算など)も組み込み
- ポイント:他ブックでも呼べるように関数をまとめておくと実務効率アップ
問題 10:自動メール送信+添付ファイル管理
模範解答
Sub SendMail()
Dim olApp As Object, olMail As Object
Dim ws As Worksheet
Dim lastRow As Long, i As Long
Set ws = ThisWorkbook.Sheets(1)
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
Set olApp = CreateObject("Outlook.Application")
For i = 2 To lastRow
Set olMail = olApp.CreateItem(0)
With olMail
.To = ws.Cells(i, 1).Value
.Subject = ws.Cells(i, 2).Value
.Body = ws.Cells(i, 3).Value
If Dir(ws.Cells(i, 4).Value) <> "" Then
.Attachments.Add ws.Cells(i, 4).Value
End If
.Send
End With
Next i
End Sub
VB解説
- Outlook を
CreateObjectで制御 - 添付ファイル存在チェック (
Dir) - エラー処理を追加すれば 大量メール送信も安全
- ポイント:Excel データ → Outlook 自動化は業務自動化の定番
✅ まとめ(問題 6〜10)
| 問題 | 技術ポイント |
|---|---|
| 6 | ChartObjects + グラフ設定 |
| 7 | FormatConditions + 条件付き書式自動生成 |
| 8 | 階層データ処理 + 再帰/インデント表示 |
| 9 | 関数モジュール化 + エラー処理 |
| 10 | Outlook 自動メール送信 + 添付ファイル管理 |
ここまでで プロレベルの VBA 設計・イベント・外部連携・自動化 が習得可能です。
問題 11:ブック間依存関係の解析
模範解答
Sub AnalyzeWorkbookDependencies()
Dim wb As Workbook
Dim ws As Worksheet
Dim lastRow As Long, i As Long
Set wb = ThisWorkbook
Set ws = wb.Sheets.Add
ws.Name = "依存関係"
ws.Cells(1, 1).Value = "シート名"
ws.Cells(1, 2).Value = "参照セル"
Dim r As Long: r = 2
Dim sh As Worksheet
For Each sh In wb.Sheets
lastRow = sh.Cells(sh.Rows.Count, 1).End(xlUp).Row
For i = 1 To lastRow
If InStr(sh.Cells(i, 1).Formula, "[") > 0 Then
ws.Cells(r, 1).Value = sh.Name
ws.Cells(r, 2).Value = sh.Cells(i, 1).Formula
r = r + 1
End If
Next i
Next sh
End Sub
VB解説
- 外部参照は
Formula内に[が含まれることが多い - 各シート・セルを走査して参照を抽出
- ポイント:依存関係を可視化することで、複雑なブックでも影響範囲を把握可能
問題 12:大規模データの分割書き出し
模範解答
Sub SplitLargeData()
Dim ws As Worksheet, newWs As Worksheet
Dim lastRow As Long, i As Long, batch As Long
Dim rowsPerSheet As Long
Set ws = ThisWorkbook.Sheets(1)
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
rowsPerSheet = 10000
batch = 1
For i = 2 To lastRow Step rowsPerSheet
Set newWs = ThisWorkbook.Sheets.Add
newWs.Name = "Batch" & batch
ws.Rows(1).Copy newWs.Rows(1) 'ヘッダーコピー
ws.Rows(i & ":" & Application.Min(i + rowsPerSheet - 1, lastRow)).Copy newWs.Rows(2)
batch = batch + 1
Next i
End Sub
VB解説
- データを指定行数ごとに分割
Application.Minで最後の端数処理- ポイント:大規模データでも Excel が重くならず安全に分割可能
問題 13:動的ピボットテーブル生成
模範解答
Sub CreatePivot()
Dim wsData As Worksheet, wsPivot As Worksheet
Dim ptCache As PivotCache, pt As PivotTable
Dim lastRow As Long, lastCol As Long
Set wsData = ThisWorkbook.Sheets(1)
Set wsPivot = ThisWorkbook.Sheets.Add
wsPivot.Name = "PivotTable"
lastRow = wsData.Cells(wsData.Rows.Count, 1).End(xlUp).Row
lastCol = wsData.Cells(1, wsData.Columns.Count).End(xlToLeft).Column
Set ptCache = ThisWorkbook.PivotCaches.Create( _
SourceType:=xlDatabase, _
SourceData:=wsData.Range(wsData.Cells(1, 1), wsData.Cells(lastRow, lastCol)))
Set pt = ptCache.CreatePivotTable(wsPivot.Cells(1, 1), "SalesPivot")
pt.PivotFields("Category").Orientation = xlRowField
pt.PivotFields("Amount").Orientation = xlDataField
pt.PivotFields("Amount").Function = xlSum
End Sub
VB解説
- 動的に範囲を取得 (
lastRow/lastCol) PivotCaches.Createでピボット作成- ポイント:ヘッダー変更や行数変更にも自動対応できる柔軟設計
問題 14:高度な文字列抽出・正規化
模範解答(RegExp 使用)
Sub ExtractPattern()
Dim regEx As Object, matches As Object
Dim txt As String, i As Long
txt = "商品123-AB, 商品456-CD, 商品789-EF"
Set regEx = CreateObject("VBScript.RegExp")
regEx.Pattern = "商品\d{3}-[A-Z]{2}"
regEx.Global = True
If regEx.Test(txt) Then
Set matches = regEx.Execute(txt)
For i = 0 To matches.Count - 1
Debug.Print matches(i)
Next i
End If
End Sub
VB解説
VBScript.RegExpで正規表現処理Patternで抽出条件指定- ポイント:複雑な文字列から特定パターンを抽出・整形する場合に必須
問題 15:API 連携(Web / JSON データ取得)
模範解答
Sub GetJsonFromAPI()
Dim http As Object, JSON As Object
Dim url As String
url = "https://api.example.com/data"
Set http = CreateObject("MSXML2.XMLHTTP")
http.Open "GET", url, False
http.Send
If http.Status = 200 Then
Dim resp As String
resp = http.responseText
'JSON パース(VBA-JSON 参照設定必須)
Set JSON = JsonConverter.ParseJson(resp)
Debug.Print JSON("data")(1)("name")
Else
MsgBox "通信エラー: " & http.Status
End If
End Sub
VB解説
MSXML2.XMLHTTPで API 呼び出し- JSON パースには外部ライブラリ(VBA-JSON)を使用
- ポイント:外部 API との連携は Excel VBA の高度な自動化・情報取得に必須
✅ まとめ(問題 11〜15)
| 問題 | 技術ポイント |
|---|---|
| 11 | ブック内外参照解析・Formula解析 |
| 12 | 大規模データ分割・シート生成 |
| 13 | 動的ピボットテーブル作成・範囲自動判定 |
| 14 | RegExp 正規表現による文字列抽出・整形 |
| 15 | Web API 連携・JSON パース・エラー処理 |
ここまでで「データ分析・自動集計・外部連携・文字列処理」のプロレベルスキルが身につきます。
問題 16:多階層ログ管理システム
模範解答
Sub LogMessage(level As String, msg As String)
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Log")
Dim lastRow As Long
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row + 1
ws.Cells(lastRow, 1).Value = Now
ws.Cells(lastRow, 2).Value = level
ws.Cells(lastRow, 3).Value = msg
'レベル別色付け
Select Case level
Case "INFO": ws.Rows(lastRow).Interior.Color = RGB(220, 230, 241)
Case "WARN": ws.Rows(lastRow).Interior.Color = RGB(255, 255, 153)
Case "ERROR": ws.Rows(lastRow).Interior.Color = RGB(255, 153, 153)
End Select
End Sub
Sub TestLog()
LogMessage "INFO", "処理開始"
LogMessage "WARN", "注意: データ欠損"
LogMessage "ERROR", "エラー発生"
End Sub
VB解説
- 日時・レベル・メッセージをシートに追記
- 行単位で色分けして視覚化
- ポイント:ログの自動管理+色分けで大規模処理の監視が容易
問題 17:ユーザーフォーム + ListBox + 動的検索
模範解答
'UserForm: frmSearch
'Controls: txtSearch (TextBox), lstResult (ListBox)
Private dataArr() As String
Public Sub LoadData()
Dim ws As Worksheet, lastRow As Long, i As Long
Set ws = ThisWorkbook.Sheets(1)
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
ReDim dataArr(1 To lastRow - 1)
For i = 2 To lastRow
dataArr(i - 1) = ws.Cells(i, 1).Value
Next i
Call FilterList("")
End Sub
Private Sub txtSearch_Change()
Call FilterList(txtSearch.Text)
End Sub
Private Sub FilterList(keyword As String)
Dim i As Long
lstResult.Clear
For i = LBound(dataArr) To UBound(dataArr)
If keyword = "" Or InStr(dataArr(i), keyword) > 0 Then
lstResult.AddItem dataArr(i)
End If
Next i
End Sub
VB解説
- 配列に全データを読み込む → ListBox に表示
txtSearch_Changeでリアルタイム検索- ポイント:大量データでも高速フィルタリングできる UI 設計
問題 18:ブック自動バックアップ
模範解答
Sub AutoBackup()
Dim backupPath As String
backupPath = "C:\Backup\"
Dim fileName As String
fileName = ThisWorkbook.Name
fileName = Left(fileName, InStrRev(fileName, ".") - 1) & "_" & Format(Now, "yyyymmdd_hhnnss") & ".xlsm"
ThisWorkbook.SaveCopyAs backupPath & fileName
End Sub
Sub ScheduleBackup()
Application.OnTime Now + TimeValue("00:30:00"), "AutoBackup"
End Sub
VB解説
SaveCopyAsで元ファイルを保持したままコピーOnTimeで定期実行可能- ポイント:業務自動化でデータ消失リスクを低減
問題 19:プロジェクト内コード自動生成
模範解答
Sub CreateModuleWithTemplate()
Dim vbProj As Object, vbComp As Object
Dim code As String
Set vbProj = ThisWorkbook.VBProject
Set vbComp = vbProj.VBComponents.Add(1) '標準モジュール
vbComp.Name = "modAutoGenerated"
code = "Sub AutoGeneratedSub()" & vbCrLf & _
" MsgBox ""自動生成コードです""" & vbCrLf & _
"End Sub"
vbComp.CodeModule.AddFromString code
End Sub
VB解説
VBComponents.Addでモジュール作成CodeModule.AddFromStringでコード挿入- ポイント:テンプレートコード自動生成で、社内マクロ開発の効率化に活用可能
- 注意:VBA プロジェクトへのアクセス許可設定が必要
問題 20:統計・分析自動化
模範解答
Sub AnalyzeData()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets(1)
Dim arr() As Double, lastRow As Long, i As Long
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
ReDim arr(1 To lastRow - 1)
For i = 2 To lastRow
arr(i - 1) = ws.Cells(i, 1).Value
Next i
Dim sumVal As Double, avgVal As Double, varVal As Double
Dim maxVal As Double, minVal As Double
sumVal = WorksheetFunction.Sum(arr)
avgVal = WorksheetFunction.Average(arr)
varVal = WorksheetFunction.Var(arr)
maxVal = WorksheetFunction.Max(arr)
minVal = WorksheetFunction.Min(arr)
ws.Cells(1, 3).Value = "合計": ws.Cells(2, 3).Value = sumVal
ws.Cells(1, 4).Value = "平均": ws.Cells(2, 4).Value = avgVal
ws.Cells(1, 5).Value = "分散": ws.Cells(2, 5).Value = varVal
ws.Cells(1, 6).Value = "最大": ws.Cells(2, 6).Value = maxVal
ws.Cells(1, 7).Value = "最小": ws.Cells(2, 7).Value = minVal
End Sub
VB解説
- 配列にデータを格納 →
WorksheetFunctionで統計計算 - Excel の関数を VBA から利用可能
- ポイント:大量データの統計・分析を自動化する基本構造
✅ まとめ(問題 16〜20)
| 問題 | 技術ポイント |
|---|---|
| 16 | ログ管理・レベル別色分け・自動追記 |
| 17 | ユーザーフォーム + ListBox + リアルタイム検索 |
| 18 | 自動バックアップ + OnTime スケジューリング |
| 19 | VBA プロジェクトにモジュール自動生成 |
| 20 | 配列統計計算 + WorksheetFunction 自動分析 |
これで プロレベル 20問の模範解答+詳細解説 が完成しました。
1問ずつ実務で使える安全設計・イベント駆動・外部連携・分析・自動化を網羅しています。

