「Excel Advent Calendar 2025」3日目の記事です。
- 学部・大学院の学生
- 研究者
- 社会人・教育関係者
あたりを主な読者として想定しています。
TL;DR
- Excel は「誰でも持っている軽量なプログラミング環境」
-
.basモジュールを 1 つ配るだけで、研究室標準の 統計・データ前処理ライブラリ を配布できる - ユーザー定義関数 (UDF) で
- 重み付き平均や z スコア、ロジット変換を「セル関数」として呼べる
- 単回帰モデルを
=LinRegPredict(...)で呼べる
- マクロで
- 調査データのクリーニング
- CSV エクスポート
を ワンクリック で再現可能にできる
Excel は、単なる表計算ではなく、
「軽量なデータサイエンス IDE」 として使えます、という話です。
はじめに:Excel は「全員がすでにインストールしている IDE」
理系の教育現場や研究室で学生に「プログラミング環境」を用意してもらうとき、よくぶつかる壁があります。
- Python / R を入れようとしてつまずく
- OS ごとに環境構築手順が違う
- バージョン差で動かないサンプルが出る
その一方で、ほぼ全員がすでに持っている のが Excel です。
- GUI でデータを触りながら
- 数式で計算ロジックを記述し
- VBA / LAMBDA / Python 連携などで自動化もできる
という意味では、Excel は
「表形式に特化した DSL (Domain Specific Language) 付きの IDE」
と見ることもできます。
本記事では、この Excel を
研究室独自の「データサイエンス用ライブラリ」
として育てるアイデアを示します。
配布単位は .bas ファイル 1 つ。
学生に配ってインポートしてもらうだけで、「研究室標準関数」が Excel に生えます。
なぜ .bas ファイルなのか?
最近の Excel には
FILTERLETLAMBDA
など、かなり強力な関数群が入りました。
これらももちろん使い倒したいのですが、複数 PC への配布 や バージョン差 を考えると、
- 素の VBA モジュール (
.bas) - ユーザー定義関数 (UDF)
- 単純なマクロ
の組み合わせは、まだまだ現役です。
.bas で配布する利点は:
- テキストファイルなので Git で管理しやすい
- 研究室サーバや LMS に置いておけば、学生が簡単にダウンロードできる
- Excel のバージョン差に比較的強い(関数名さえ気をつければ)
ということで、この記事では .bas モジュールとして
- 統計 / データサイエンス用 UDF 集
- 単回帰モデルの関数化
- データクリーニング + CSV エクスポートのマクロ
を作ってみます。
Step 1: 統計・データサイエンス用 UDF を追加する
まずは「よく使うけれど、毎回関数を組み立てるのは面倒」な処理を
UDF (User Defined Function) としてまとめます。
ここでは例として、以下を実装します。
- 重み付き平均
WeightedAverage - z スコア
ZScore - ロジット変換
Logit
modStatsUDF.bas の全体コード
.bas として保存できるよう、標準モジュールを丸ごと載せます。
' ===== modStatsUDF.bas =====
Option Explicit
'-----------------------------------------------
' 重み付き平均
' =WeightedAverage(値の範囲, 重みの範囲)
' 例: =WeightedAverage(B2:B11, C2:C11)
'-----------------------------------------------
Public Function WeightedAverage(ByVal values As Range, _
ByVal weights As Range) As Variant
Dim sumVW As Double
Dim sumW As Double
Dim c As Range
Dim i As Long
If values.Count <> weights.Count Then
WeightedAverage = CVErr(xlErrRef)
Exit Function
End If
i = 0
For Each c In values.Cells
i = i + 1
If IsNumeric(c.Value) And IsNumeric(weights.Cells(i).Value) Then
sumVW = sumVW + CDbl(c.Value) * CDbl(weights.Cells(i).Value)
sumW = sumW + CDbl(weights.Cells(i).Value)
End If
Next c
If sumW = 0 Then
WeightedAverage = CVErr(xlErrDiv0)
Else
WeightedAverage = sumVW / sumW
End If
End Function
'-----------------------------------------------
' zスコア
' =ZScore(対象値, サンプル範囲)
' 例: =ZScore(A2, $A$2:$A$101)
'-----------------------------------------------
Public Function ZScore(ByVal x As Double, _
ByVal sampleRange As Range) As Variant
Dim mu As Double
Dim sigma As Double
On Error GoTo ErrHandler
If sampleRange.Count < 2 Then
ZScore = CVErr(xlErrNA)
Exit Function
End If
mu = WorksheetFunction.Average(sampleRange)
sigma = WorksheetFunction.StDev_S(sampleRange)
If sigma = 0 Then
ZScore = CVErr(xlErrDiv0)
Else
ZScore = (x - mu) / sigma
End If
Exit Function
ErrHandler:
ZScore = CVErr(xlErrValue)
End Function
'-----------------------------------------------
' ロジット変換
' =Logit(p)
' 0 < p < 1 以外ではエラー
' 例: =Logit(0.3)
'-----------------------------------------------
Public Function Logit(ByVal p As Double) As Variant
If p <= 0 Or p >= 1 Then
Logit = CVErr(xlErrNum)
Else
Logit = WorksheetFunction.Ln(p / (1 - p))
End If
End Function
使い方イメージ
例えば、学生の成績データが次のようにあるとします。
| 学籍番号 | 得点 | 単位数(重み) |
|---|---|---|
| A001 | 80 | 2 |
| A002 | 90 | 1 |
| ... | ... | ... |
このとき、重み付き平均 GPA をセルに出したければ、
=WeightedAverage(B2:B11, C2:C11)
と書くだけで済みます。
z スコアも
=ZScore(B2, $B$2:$B$101)
のように、統計教科書に出てくる記号そのまま の感覚で書けます。
Logit を使えば、ロジスティック回帰の前処理などで登場する
ロジット変換を Excel のセルの中だけで完結させることもできます。
Step 2: 単回帰モデルを Excel 関数として生やす
次に、もっとデータサイエンス寄りの例として 単回帰モデル を関数化してみます。
やりたいこと
- 説明変数
X、目的変数Yのデータから- 傾き
b1 - 切片
b0
- 傾き
- さらに、新しい
x_newを入力すると- 予測値
ŷ = b1 * x_new + b0を返す
- 予測値
つまり、Excel のセルで
=LinRegSlope($A$2:$A$101, $B$2:$B$101)
=LinRegPredict(C2, $A$2:$A$101, $B$2:$B$101)
のように書けるようにします。
modRegression.bas の全体コード
' ===== modRegression.bas =====
Option Explicit
'-----------------------------------------------
' 単回帰の傾き
' =LinRegSlope(X範囲, Y範囲)
'-----------------------------------------------
Public Function LinRegSlope(ByVal XRange As Range, _
ByVal YRange As Range) As Variant
Dim coefs As Variant
If XRange.Count <> YRange.Count Then
LinRegSlope = CVErr(xlErrRef)
Exit Function
End If
On Error GoTo ErrHandler
' LinEst は {傾き, 切片; …} のような配列を返す
coefs = WorksheetFunction.LinEst(YRange, XRange, True, True)
LinRegSlope = coefs(1, 1)
Exit Function
ErrHandler:
LinRegSlope = CVErr(xlErrValue)
End Function
'-----------------------------------------------
' 単回帰の切片
' =LinRegIntercept(X範囲, Y範囲)
'-----------------------------------------------
Public Function LinRegIntercept(ByVal XRange As Range, _
ByVal YRange As Range) As Variant
Dim coefs As Variant
If XRange.Count <> YRange.Count Then
LinRegIntercept = CVErr(xlErrRef)
Exit Function
End If
On Error GoTo ErrHandler
coefs = WorksheetFunction.LinEst(YRange, XRange, True, True)
LinRegIntercept = coefs(1, 2)
Exit Function
ErrHandler:
LinRegIntercept = CVErr(xlErrValue)
End Function
'-----------------------------------------------
' 新しい X に対する予測値
' =LinRegPredict(x, X範囲, Y範囲)
'-----------------------------------------------
Public Function LinRegPredict(ByVal x As Double, _
ByVal XRange As Range, _
ByVal YRange As Range) As Variant
Dim b1 As Variant
Dim b0 As Variant
b1 = LinRegSlope(XRange, YRange)
b0 = LinRegIntercept(XRange, YRange)
If IsError(b1) Or IsError(b0) Then
LinRegPredict = CVErr(xlErrValue)
Else
LinRegPredict = b1 * x + b0
End If
End Function
授業・研究での使いどころ
- 学部の実験レポートで「検量線を引いて、未知試料の濃度を推定せよ」という課題
-
X:既知濃度 -
Y:測定信号 -
LinRegSlope,LinRegIntercept,LinRegPredictで 線形フィットと推定をセルで再現
-
- 卒論・修論の初期解析で
「とりあえず単回帰で傾向だけ見たい」時に
Python / R を立ち上げる前の試行錯誤用として
もちろん真面目に統計解析するなら R / Python に行くべきですが、
「とりあえずやってみて直感を掴む」 段階では、Excel のグリッドとグラフ機能は非常に強力です。
Step 3: クリーニングとエクスポートをワンクリックにする
データサイエンスの現場では、
モデルより前に、まず前処理で死ぬ
ことがよくあります。
Excel で CSV を少しだけ整えてから R / Python に渡す、というフローはよく見かけますが、
- 空行削除
- 文字列の前後空白削除
- CSV エクスポート
を 毎回手作業でやっている と、再現性も効率も悪いです。
そこで、これらをまとめてやってくれるマクロを用意しておきます。
modDataCleaning.bas の全体コード
' ===== modDataCleaning.bas =====
Option Explicit
'-----------------------------------------------
' アクティブシートの簡易クリーニング
' 1. 2行目以降の「完全に空の行」を削除
' 2. 文字列セルの前後空白を削除
'-----------------------------------------------
Public Sub CleanSurveyData()
Dim ws As Worksheet
Dim lastRow As Long
Dim lastCol As Long
Dim r As Long
Dim c As Long
Set ws = ActiveSheet
Application.ScreenUpdating = False
lastRow = ws.Cells(ws.Rows.Count, 1).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, 1).End(xlUp).Row
' 文字列セルの前後空白を削除
For r = 2 To lastRow
For c = 1 To lastCol
With ws.Cells(r, c)
If VarType(.Value) = vbString Then
.Value = Trim(.Value)
End If
End With
Next c
Next r
Application.ScreenUpdating = True
End Sub
'-----------------------------------------------
' アクティブシートをUTF-8のCSVとしてエクスポート
' ・ファイル名: シート名_yyyymmdd_HHMMSS.csv
' ・元ブックはそのまま
'-----------------------------------------------
Public Sub ExportCurrentSheetAsCsv()
Dim ws As Worksheet
Dim filePath As String
Dim tempBook As Workbook
Set ws = ActiveSheet
If ThisWorkbook.Path = "" Then
MsgBox "まずブックを保存してください。", vbExclamation
Exit Sub
End If
filePath = ThisWorkbook.Path & "\" & _
ws.Name & "_" & Format(Now, "yyyymmdd_HHMMSS") & ".csv"
Application.ScreenUpdating = False
' シートだけを別ブックにコピーしてから保存
ws.Copy
Set tempBook = ActiveWorkbook
tempBook.SaveAs Filename:=filePath, FileFormat:=xlCSVUTF8
tempBook.Close SaveChanges:=False
Application.ScreenUpdating = True
MsgBox "CSVを書き出しました:" & vbCrLf & filePath, vbInformation
End Sub
実運用のイメージ
- Web フォームや Google フォームから CSV をダウンロード
- Excel で開く
- リボンに「クイックアクセスツールバー」をカスタマイズし、
CleanSurveyData-
ExportCurrentSheetAsCsv
をボタンとして配置
- ボタンをポチッとすると
- 余計な空行や空白が消え
- 一定の命名規則に沿った CSV が書き出される
この CSV をそのまま R / Python のスクリプトに食わせれば、
「Excel でちょっと整える → スクリプトで解析 → 図表をレポートに貼る」
という 再現可能なパイプライン が簡単に作れます。
.bas ファイルとして配布・再利用する手順
上で示した 3 つのモジュール
modStatsUDF.basmodRegression.basmodDataCleaning.bas
を研究室や授業で配布する場合の手順です。
1. 教員側:.bas として保存
- Excel で
Alt + F11を押して VBA エディタを開く - 「挿入」→「標準モジュール」でモジュールを追加
- この記事のコードを丸ごとコピペする
- プロジェクトエクスプローラで対象モジュールを右クリック
- 「ファイルのエクスポート」で
.basとして保存
例:modStatsUDF.basなど
保存した .bas を
- GitHub / GitLab などのリポジトリ
- 研究室の共有フォルダ
- LMS (Moodle / Google Classroom など)
に置いておきます。
2. 学生・利用者側:インポート
-
.basファイルをダウンロード - Excel でブックを開き、
Alt + F11で VBA エディタへ - プロジェクトエクスプローラ上で
- 目的のブックを選択し右クリック
- 「ファイルのインポート」から
.basを選択
- 元の Excel に戻ると、セルで
=WeightedAverage(...)=ZScore(...)-
=LinRegPredict(...)
がそのまま使えるようになっています
これだけで
「研究室標準の関数群を、どの学生の Excel にも再現」
できるようになります。
関数 (LET / LAMBDA) や Python との相性
本記事は VBA 中心でしたが、近年の Excel では
-
LETで数式内に変数を導入 -
LAMBDAで数式ベースの関数を作成 - Python 連携 (環境によっては Excel から直接 Python が呼べる)
といった発展も進んでいます。
個人的には、次のような使い分けがしっくりきます。
-
VBA (.bas)
- 研究室全体・授業全体で共有したい「標準ライブラリ」
- ファイル操作や UI 操作(ボタンなど)を伴うワークフロー
-
LAMBDA
- そのブック内だけで完結するロジック
- 他者の環境依存を避けたいとき(マクロ無効の環境など)
-
Python / R
- 本格的な統計モデリング・機械学習
- 大規模データ / 高度な可視化
Excel を 窓口 として使いつつ、段階的に外部ツールへ接続していくと、学生にとっての学習コストも抑えやすくなります。
まとめ
- Excel は「表計算ソフト」であると同時に、誰もが持っている プログラミング環境 でもある
-
.basモジュールを 1 つ配るだけで- 統計・データサイエンス向け UDF
- 単回帰モデルの関数
- データクリーニング & CSV エクスポート
を研究室・授業の標準機能として配布できる
- これにより、Excel が
- 手作業の道具 から
- 再現可能なワークフローを記述するための「軽量 DSL」
に一歩近づく
Excel Advent Calendar 2025 では、他の参加者の方が
FILTER / LET / LAMBDA / Python 連携 など、
もっと別の切り口から Excel の可能性を掘ってくださるはずです。
本記事が、「研究室や授業での Excel の使い方を、もう一段階だけ踏み込んでみる」きっかけになれば幸いです。