「Excel Advent Calendar 2025」の一記事です。
この記事では Excel VBA にフォーカスし、
- まったくの基本から
- 教育・研究の現場で使える自動化
- データサイエンス的な応用
まで、1本のストーリーとして紹介します。
想定読者は、
- 理系・文理問わず大学の教員
- 研究室で Excel を多用している学生・ポスドク
- R / Python も使うが、日常は Excel が主戦場という方
です。
TL;DR
- Excel VBA は「Excelを特化型IDEに変えるスクリプト言語」
- 教育・研究でよくある
- 成績管理
- アンケート集計
- 実験データの前処理
を ワンクリック で再現可能にできる
- 基本は
-
Range/Cellsへのアクセス -
For Each/Ifといった制御構文 -
WorksheetFunctionの活用
-
- 少し踏み込むと
- 外れ値の自動ハイライト
- サマリーシートの自動生成
- CSV 書き出し → R / Python 解析への橋渡し
といった 軽量データ基盤 を研究室に用意できる
1. 今日作る「ミニ・データ基盤」のイメージ
この記事では、次のような Excel ブックをゴールにします。
-
Rawシート
→ LMS や Google フォームから落としてきた 生データ を貼るだけ -
Summaryシート
→ ボタン1つで- 質問ごとの平均・標準偏差
- 回答数
が自動計算される
-
Scoresシート
→ 成績一覧。外れ値(zスコア ±2 以上)を自動ハイライト -
Exportマクロ
→ R / Python 用の CSV をワンクリックで書き出す
これらを支える VBA モジュールを
- 基本
- 中級(実務的なループ・条件分岐)
- 応用(イベント・他ツール連携)
という順で作っていきます。
2. Excel VBA の「超」基本:オブジェクトと最初のマクロ
2.1 開発環境を開く
環境構築はほぼ不要ですが、最初にだけ設定が必要です。
- Excel で「開発」タブを表示
- [ファイル] → [オプション] → [リボンのユーザー設定] → 「開発」にチェック
- [開発] タブ → [Visual Basic] をクリック(または
Alt + F11) - VBA エディタが開くので
- [挿入] → [標準モジュール] で新しいモジュールを追加
モジュールに次のコードを書いてみます。
Option Explicit
Public Sub HelloVBA()
MsgBox "こんにちは、VBAの世界へ"
End Sub
Excel 側に戻り、「開発」タブ →「マクロ」→ HelloVBA →「実行」で
メッセージボックスが出れば成功です。
2.2 Excel VBA の3つのキーワード
VBA を「Excel を操る言語」として見ると、最初に意識しておくとよいのが次の3つです。
-
Application… Excel 全体 -
Workbook… ブック -
Worksheet/Range… シートとセル
最初の目標は、
「どのシートの、どのセルに、何をするか」をコードで書けるようになること
です。
例:アクティブシートの A1 にタイトルを書き込むマクロ。
Public Sub WriteTitle()
Dim ws As Worksheet
Set ws = ActiveSheet
ws.Range("A1").Value = "授業アンケート生データ"
ws.Range("A1").Font.Bold = True
End Sub
-
Set ws = ActiveSheet
→ いきなりActiveSheetを何度も書くより、変数に置いた方が読みやすい -
Range("A1")
→ 特定セル -
.Value,.Font.Bold
→ オブジェクトの「プロパティ」
3. 基本パターン:ループと条件分岐で「行を回す」
教育・研究の現場で一番使うのは、「行ごとに何かをする」パターンです。
3.1 行ループの定番テンプレート
Public Sub LoopRowsTemplate()
Dim ws As Worksheet
Dim lastRow As Long
Dim r As Long
Set ws = ActiveSheet
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
For r = 2 To lastRow ' 1行目はヘッダと仮定
' A列の値を取得
Dim id As String
id = ws.Cells(r, "A").Value
' ここに条件分岐や処理を書く
If id <> "" Then
' 何か処理
End If
Next r
End Sub
-
lastRowで「データが入っている最終行」を取得 -
For r = 2 To lastRowで 2 行目以降を順番に処理 -
Cells(行, 列)でセルにアクセス
このテンプレさえ書ければ、アンケート・成績・実験データのほとんどの処理は表現できます。
4. 実例1:アンケートのクレンジングマクロ
まずは「生データをきれいにする」VBA から。
4.1 Rawシートの前提
Raw シートに、こんな感じのデータがあるとします。
| 学籍番号 | 学科 | Q1 | Q2 | Q3 |
|---|---|---|---|---|
| A001 | 物理 | 5 | 4 | 5 |
| A002 | 情報 | 4 | 3 | 4 |
| ... | ... | … | … | … |
ただし実際には、
- 空行が混じっている
- 前後にスペースが入っている
- 「N/A」「NA」などの文字列が混じっている
といった「研究室あるある」状態。
これを
- 完全に空の行を削除
- 文字列の前後スペース除去
-
NAなどを空白にそろえる
マクロで一気に処理します。
4.2 クレンジングマクロのコード
Option Explicit
Public Sub CleanRawSurvey()
Dim ws As Worksheet
Dim lastRow As Long
Dim lastCol As Long
Dim r As Long, c As Long
Set ws = ThisWorkbook.Worksheets("Raw")
Application.ScreenUpdating = False
' 最終行・最終列を取得
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
lastCol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
' 末尾から空行削除(上から消すと行番号がずれる)
For r = lastRow To 2 Step -1
If Application.WorksheetFunction.CountA(ws.Rows(r)) = 0 Then
ws.Rows(r).Delete
End If
Next r
' 再取得
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
' 文字列をトリムしつつ NA 系を空白に
For r = 2 To lastRow
For c = 1 To lastCol
With ws.Cells(r, c)
If VarType(.Value) = vbString Then
Dim s As String
s = Trim$(.Value)
If s = "NA" Or s = "N/A" Or s = "-" Then
.Value = ""
Else
.Value = s
End If
End If
End With
Next c
Next r
Application.ScreenUpdating = True
MsgBox "Rawシートのクレンジングが完了しました。", vbInformation
End Sub
ポイント:
-
Application.ScreenUpdating = False
→ 高速化 + チラつき防止 -
CountAで「完全に空の行」を判定 -
VarTypeで文字列セルだけ処理 - 「NA」「N/A」「-」などを空白に統一
LMS やフォームから落としたCSVを Raw に貼り付け、
このマクロをボタンやショートカットに割り当てておけば、
毎回同じクレンジングを忘れず再現できます。
5. 実例2:Summaryシートに統計サマリを自動生成
次は、Raw のデータから
- 各質問(Q1〜Q3)について
- 平均
- 標準偏差
- 有効回答数
を Summary シートに自動で書き出すマクロを作ります。
5.1 やりたいこと
Summary シートを次のような形にしたい:
| 質問 | 平均 | 標準偏差 | 回答数 |
|---|---|---|---|
| Q1 | 4.2 | 0.8 | 95 |
| Q2 | 3.9 | 1.1 | 95 |
| Q3 | 4.5 | 0.6 | 95 |
ここでは VBAで数式を生成 し、
集計ロジックは Excel 関数 (AVERAGE, STDEV.S, COUNTA) に任せるスタイルにします。
5.2 Summary生成マクロのコード
Public Sub BuildSummarySheet()
Dim wsRaw As Worksheet
Dim wsSum As Worksheet
Dim lastRow As Long
Dim lastCol As Long
Dim qColStart As Long
Dim qCol As Long
Dim outRow As Long
Set wsRaw = ThisWorkbook.Worksheets("Raw")
' Summaryシートを用意(なければ作る)
On Error Resume Next
Set wsSum = ThisWorkbook.Worksheets("Summary")
On Error GoTo 0
If wsSum Is Nothing Then
Set wsSum = ThisWorkbook.Worksheets.Add(After:=wsRaw)
wsSum.Name = "Summary"
End If
' Summaryシートを初期化
wsSum.Cells.Clear
' Rawの最終行・列
lastRow = wsRaw.Cells(wsRaw.Rows.Count, "A").End(xlUp).Row
lastCol = wsRaw.Cells(1, wsRaw.Columns.Count).End(xlToLeft).Column
' ヘッダ行
wsSum.Range("A1:D1").Value = Array("質問", "平均", "標準偏差", "回答数")
wsSum.Range("A1:D1").Font.Bold = True
' 質問列は Raw の3列目以降(Q1, Q2, ...)と仮定
qColStart = 3
outRow = 2
For qCol = qColStart To lastCol
Dim qName As String
qName = wsRaw.Cells(1, qCol).Value ' "Q1" など
If qName <> "" Then
wsSum.Cells(outRow, 1).Value = qName
' 平均
wsSum.Cells(outRow, 2).Formula = _
"=AVERAGE(" & wsRaw.Name & "!" & _
wsRaw.Range(wsRaw.Cells(2, qCol), wsRaw.Cells(lastRow, qCol)).Address(False, False) & ")"
' 標準偏差
wsSum.Cells(outRow, 3).Formula = _
"=STDEV.S(" & wsRaw.Name & "!" & _
wsRaw.Range(wsRaw.Cells(2, qCol), wsRaw.Cells(lastRow, qCol)).Address(False, False) & ")"
' 回答数(空白除く)
wsSum.Cells(outRow, 4).Formula = _
"=COUNTA(" & wsRaw.Name & "!" & _
wsRaw.Range(wsRaw.Cells(2, qCol), wsRaw.Cells(lastRow, qCol)).Address(False, False) & ")"
outRow = outRow + 1
End If
Next qCol
wsSum.Columns("A:D").AutoFit
MsgBox "Summaryシートを更新しました。", vbInformation
End Sub
ポイント:
- Summary シートがなければ 自動で追加
- 列方向にループして、質問列(Q1〜)を動的に検出
- 数式は
Range.Address(False, False)で「絶対参照/相対参照」を制御 - 集計処理そのものは Excel 関数に委譲
教員視点では、
「Raw に貼ってボタンを押せば、集計表が毎回同じ形で再計算される」
という状態になるので、採点・集計の再現性 が上がります。
6. 実例3:成績シートで外れ値を自動ハイライト
次は、少し「データサイエンス」寄りの例として、
成績シートで z スコアを使って外れ値を自動で塗るマクロです。
6.1 Scoresシートの前提
Scores シートに次のようなデータがあるとします。
| 学籍番号 | テスト得点 | レポート得点 | 総合点 |
|---|---|---|---|
| A001 | 80 | 70 | 76 |
| A002 | 92 | 88 | 90 |
| ... | ... | ... | ... |
ここで、「テスト得点」の外れ値を
- 平均 ± 2σ を超えるものを赤背景にする
という処理を VBA で実装します。
6.2 外れ値ハイライトマクロ
Public Sub HighlightScoreOutliers()
Dim ws As Worksheet
Dim lastRow As Long
Dim scoreRange As Range
Dim cell As Range
Dim mu As Double
Dim sigma As Double
Dim z As Double
Set ws = ThisWorkbook.Worksheets("Scores")
' テスト得点は列Bと仮定
lastRow = ws.Cells(ws.Rows.Count, "B").End(xlUp).Row
Set scoreRange = ws.Range("B2:B" & lastRow)
' 平均と標準偏差を WorksheetFunction で取得
mu = Application.WorksheetFunction.Average(scoreRange)
sigma = Application.WorksheetFunction.StDev_S(scoreRange)
' いったん色をリセット
scoreRange.Interior.ColorIndex = xlNone
' 各セルのzスコアを計算して判定
For Each cell In scoreRange
If IsNumeric(cell.Value) And sigma <> 0 Then
z = (cell.Value - mu) / sigma
If Abs(z) >= 2 Then
cell.Interior.Color = vbRed
cell.Font.Color = vbWhite
End If
End If
Next cell
MsgBox "外れ値(|z|>=2)をハイライトしました。", vbInformation
End Sub
-
WorksheetFunction.Average/StDev_Sで統計量を取得 - ループ内で z スコアを計算し、閾値で色付け
- Excel関数でやることもできますが、VBA による可視化ロジックとしてまとめておくと、
- 「どこからが外れ値か」の定義を明示できる
- 条件を後から一括変更しやすい
授業で「標準化」「外れ値検出」の話をするときに、
Excel シート上で視覚的に見せるのにちょうどいい題材です。
7. 実例4(応用):R / Python 解析用の CSV をワンクリックで出力
VBA のおかげで 「Excel → R / Python」 の橋渡しも楽になります。
ここでは、
-
Rawシートのきれいになったデータを - UTF-8 の CSV として
-
exportフォルダに書き出す
マクロを作ります。
Public Sub ExportRawForR()
Dim ws As Worksheet
Dim tempBook As Workbook
Dim exportPath As String
Dim exportFolder As String
Set ws = ThisWorkbook.Worksheets("Raw")
If ThisWorkbook.Path = "" Then
MsgBox "まずブックを保存してください。", vbExclamation
Exit Sub
End If
exportFolder = ThisWorkbook.Path & "\export"
' exportフォルダがなければ作成
If Dir(exportFolder, vbDirectory) = "" Then
MkDir exportFolder
End If
exportPath = exportFolder & "\" & "survey_" & Format(Now, "yyyymmdd_HHMMSS") & ".csv"
Application.ScreenUpdating = False
' シートだけを新しいブックにコピーして保存
ws.Copy
Set tempBook = ActiveWorkbook
tempBook.SaveAs Filename:=exportPath, FileFormat:=xlCSVUTF8
tempBook.Close SaveChanges:=False
Application.ScreenUpdating = True
MsgBox "CSVを書き出しました:" & vbCrLf & exportPath, vbInformation
End Sub
これで、R / Python 側では
-
exportフォルダを監視しておく - 最新ファイルを読み込んで解析
といったスクリプトを用意しておけば、
Excel でボタン → CSV 書き出し → R / Python で解析 → 図をレポートに貼る
というパイプラインを簡単に回せます。
8. さらに一歩:イベントマクロで「入力した瞬間に反応させる」
ここまでのマクロはすべて「メニューから実行する」タイプでした。
VBA のもう一段階上の使い方として、
「セルが変更された瞬間に自動で処理を走らせる」
イベントマクロがあります。
8.1 例:成績入力時に自動で外れ値チェック
Scores シートのコードモジュール(標準モジュールではなく、
VBAプロジェクトの中の「Sheet(Scores)」ダブルクリック)に、次のコードを書きます。
Private Sub Worksheet_Change(ByVal Target As Range)
' 列B(テスト得点)が変更されたときだけ反応
If Intersect(Target, Me.Range("B2:B1000")) Is Nothing Then Exit Sub
' 安全のため、複数セル変更はスルー
If Target.CountLarge > 1 Then Exit Sub
' 全体を再チェック
HighlightScoreOutliers
End Sub
-
Worksheet_Changeは、このシートでセルが変更されたときに自動で呼ばれる -
Intersectで「どの列が変わったか」を判定 - 先ほどの
HighlightScoreOutliersを呼ぶ
これで、成績を入力・修正した瞬間に
外れ値の色付けが常に最新状態 になります。
イベントマクロは便利な反面、「いつ誰がどこで動いているかわかりにくくなる」危険もあるので、コメントと設計を丁寧にしておくのが大事です。
9. 研究室向け「VBAライブラリ」として育てる
ここまで紹介してきたマクロを含む標準モジュールを
modRawTools.basmodSummaryTools.basmodScoreTools.bas
などとして .bas ファイルに書き出しておけば、
それ自体が 研究室向けの共通VBAライブラリ になります。
9.1 エクスポート・インポートの手順(復習)
教員側(配布側)
- VBAエディタで対象モジュールを右クリック
- 「ファイルのエクスポート」
-
modLabTools.basなどの名前で保存 - 研究室の共有フォルダや Git リポジトリに置いておく
学生側(利用側)
-
.basファイルをダウンロード -
Alt + F11で VBAエディタを開く - プロジェクトを右クリック →「ファイルのインポート」
-
modLabTools.basを選択
これだけで、研究室標準の
- データクレンジングマクロ
- サマリ生成マクロ
- 外れ値ハイライト
- CSVエクスポート
などが、学生の Excel に「機能」として生えます。
R / Python のパッケージ配布に比べて、
Excelしか使えない人でも恩恵を受けられる のが大きな利点です。
10. まとめ:Excel VBA は「身近な実験用ランタイム」
この記事では、教育・研究の現場を念頭に置きながら
- VBAの基本(オブジェクト・ループ・条件分岐)
- アンケートのクレンジング
- 統計サマリの自動生成
- 成績の外れ値ハイライト
- R / Python への橋渡しとしての CSV エクスポート
- イベントマクロによる「自動反応するシート」
といった流れで Excel VBA を見直してみました。
改めて整理すると、Excel VBA は
- ExcelというGUI + 表形式データ に特化した
- 軽量で、誰でも持っている
- 実験的なスクリプトをすぐ書いて試せる
「身近な実験用ランタイム」です。
R / Python で本格的なデータサイエンスに進んでいくための 前段階 としても、
- データの意味を行・列レベルで意識させる
- データ処理パイプラインをコードで表現する
- 同じ処理を何度も再現可能にする
といった思考様式を、Excel VBA を通じて学ばせることができます。
Excel Advent Calendar 2025 では、他の参加者の方が
LAMBDA や Python連携、より高度な VBA テクニックなどを
さらに掘り下げてくださると思います。
本記事が、
「とりあえずこの授業・この研究室用の標準マクロを1つ作ってみよう」
と思ってもらえるきっかけになれば幸いです。
(「こういう処理をVBAで自動化したい」「このデータをどう扱うか悩んでいる」といったご相談があれば、コメントで教えてください。)