ねらい:処理対象列を「自動判定」して人手を減らす
毎回「この列を処理する」と手で指定していませんか?大規模や可変フォーマットのシートでは、列位置が変わる、ヘッダー名が違う、空列が混ざる…などでミスが増えます。そこで、ヘッダー名やデータの特徴から「処理対象列を自動判定」するテンプレートを用意します。初心者でも貼って使える形で、重要ポイントを深掘りして解説します。
- 目的: 列位置に依存しない堅牢な処理(ヘッダー名・部分一致・型判定・優先度)。
- 考え方: 1) 候補列を抽出 → 2) ルールでスコア付け → 3) 最適列を採用 → 4) 例外時はフォールバック。
- 重要ポイント(深掘り): ヘッダーで決め打ちせず、複数ルールを組み合わせると変化に強い。エラー時には「見つからなかった」ログ・ガードを必ず入れる。
基本テンプレ:ヘッダー名で確定(完全一致)
最もシンプルな方法。ヘッダー行から列番号を見つけます。
Function FindColumnByHeader(ByVal ws As Worksheet, ByVal headerRow As Long, ByVal headerName As String) As Long
Dim lastCol As Long: lastCol = ws.Cells(headerRow, ws.Columns.Count).End(xlToLeft).Column
Dim c As Long
For c = 1 To lastCol
If CStr(ws.Cells(headerRow, c).Value) = headerName Then
FindColumnByHeader = c
Exit Function
End If
Next
FindColumnByHeader = 0 ' 見つからない場合
End Function
Sub Example_FindExact()
Dim ws As Worksheet: Set ws = Worksheets("Input")
Dim colEmpNo As Long: colEmpNo = FindColumnByHeader(ws, 1, "社員番号")
If colEmpNo = 0 Then
MsgBox "社員番号列が見つかりません。"
Exit Sub
End If
MsgBox "社員番号列は " & Split(ws.Cells(1, colEmpNo).Address(0, 0), "$")(0) & " 列です。"
End Sub
VB- 深掘り: 完全一致は速くて堅いが、表記ゆれや別名(例:社員ID、従業員番号)に弱い。実務では次の部分一致・同義語セットまで用意すると安定する。
応用テンプレ:部分一致+同義語(ゆれ吸収)
複数候補名で最適列を探します。最初に見つかったものを採用するか、優先順位をつけます。
Function FindColumnByAliases(ByVal ws As Worksheet, ByVal headerRow As Long, ByRef aliases As Variant) As Long
Dim lastCol As Long: lastCol = ws.Cells(headerRow, ws.Columns.Count).End(xlToLeft).Column
Dim c As Long, i As Long, head As String
For c = 1 To lastCol
head = CStr(ws.Cells(headerRow, c).Value)
For i = LBound(aliases) To UBound(aliases)
If head Like "*" & aliases(i) & "*" Then
FindColumnByAliases = c
Exit Function
End If
Next
Next
FindColumnByAliases = 0
End Function
Sub Example_FindAliases()
Dim ws As Worksheet: Set ws = Worksheets("Input")
Dim names As Variant: names = Array("社員番号", "社員ID", "従業員番号")
Dim col As Long: col = FindColumnByAliases(ws, 1, names)
If col = 0 Then
MsgBox "社員番号系の列が見つかりません。"
Else
MsgBox "対象列は " & Split(ws.Cells(1, col).Address(0, 0), "$")(0) & " 列です。"
End If
End Sub
VB- 深掘り: 「部分一致」は柔軟だが、誤検知が起き得る(例:備考に“番号表記について”)。後述の型判定やサンプルチェックと組み合わせると精度が上がる。
信頼度アップ:サンプル行の型でスコアリング
ヘッダーだけでなく、複数行のデータ形(全部数字、日付が多い、文字長が一定)でスコア評価し、最も条件を満たす列を選びます。
Function GuessBestNumericColumn(ByVal ws As Worksheet, ByVal headerRow As Long, _
ByVal startRow As Long, ByVal endRow As Long) As Long
Dim lastCol As Long: lastCol = ws.Cells(headerRow, ws.Columns.Count).End(xlToLeft).Column
Dim c As Long, r As Long, score As Long, bestScore As Long, bestCol As Long
bestScore = -1
For c = 1 To lastCol
score = 0
For r = startRow To endRow
Dim v As Variant: v = ws.Cells(r, c).Value
If Len(CStr(v)) = 0 Then GoTo ContinueRow
If IsNumeric(v) Then
' 整数なら加点
If CDbl(v) = Int(CDbl(v)) Then score = score + 2 Else score = score + 1
Else
' 非数なら減点
score = score - 1
End If
ContinueRow:
Next
If score > bestScore Then
bestScore = score
bestCol = c
End If
Next
GuessBestNumericColumn = bestCol
End Function
Sub Example_GuessNumeric()
Dim ws As Worksheet: Set ws = Worksheets("Input")
Dim lastRow As Long: lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
Dim sampleEnd As Long: sampleEnd = WorksheetFunction.Min(lastRow, 101) ' 100行サンプル
Dim col As Long: col = GuessBestNumericColumn(ws, 1, 2, sampleEnd)
MsgBox "数値っぽい列の推定結果: " & Split(ws.Cells(1, col).Address(0, 0), "$")(0)
End Sub
VB- 深掘り(重要):
- サンプル数は「多すぎず少なすぎず」。100〜200行で十分なことが多い。
- スコア設計はルール次第。例えば「電話番号は10〜11桁の数字」「社員番号は6桁の数字」など、業務ルールで加点条件を追加すると精度が劇的に上がる。
総合テンプレ:ヘッダー候補+型スコア+優先順位
複数の判定を合成して「最も妥当」な列を選ぶフレーム。
Function AutoDetectColumn(ByVal ws As Worksheet, ByVal headerRow As Long, _
ByVal startRow As Long, ByVal endRow As Long, _
ByRef aliases As Variant, ByVal expectLen As Long, _
Optional ByVal preferHeader As Boolean = True) As Long
Dim lastCol As Long: lastCol = ws.Cells(headerRow, ws.Columns.Count).End(xlToLeft).Column
Dim c As Long, head As String
Dim bestCol As Long: bestCol = 0
Dim bestScore As Long: bestScore = -100000
For c = 1 To lastCol
head = CStr(ws.Cells(headerRow, c).Value)
' 基本スコア(ヘッダー一致)
Dim score As Long: score = 0
Dim i As Long
For i = LBound(aliases) To UBound(aliases)
If head Like "*" & aliases(i) & "*" Then
score = score + IIf(preferHeader, 50, 20) ' ヘッダー優先度
Exit For
End If
Next
' データスコア(サンプル判定)
Dim r As Long
For r = startRow To endRow
Dim v As Variant: v = ws.Cells(r, c).Value
If Len(CStr(v)) = 0 Then GoTo ContinueRow
If IsNumeric(v) Then
' 桁数が期待に近いほど加点(社員番号など)
Dim s As String: s = CStr(v)
If Len(s) = expectLen Then
score = score + 5
ElseIf Abs(Len(s) - expectLen) <= 2 Then
score = score + 2
Else
score = score + 1
End If
Else
score = score - 2
End If
ContinueRow:
Next
If score > bestScore Then
bestScore = score
bestCol = c
End If
Next
AutoDetectColumn = bestCol
End Function
Sub Example_AutoDetect_EmployeeNo()
Dim ws As Worksheet: Set ws = Worksheets("Input")
Dim lastRow As Long: lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
Dim sampleEnd As Long: sampleEnd = WorksheetFunction.Min(lastRow, 102)
Dim aliases As Variant: aliases = Array("社員番号", "社員ID", "従業員番号")
Dim col As Long: col = AutoDetectColumn(ws, 1, 2, sampleEnd, aliases, 6, True)
If col = 0 Then
MsgBox "対象列が自動判定できませんでした。"
Else
MsgBox "自動判定した列: " & Split(ws.Cells(1, col).Address(0, 0), "$")(0) & "(" & ws.Cells(1, col).Value & ")"
End If
End Sub
VB- 深掘り(重要):
- 「ヘッダー名の信頼度」「データ形の信頼度」を重みづけして合計スコア→最良列。
- 誤検知対策として「最低スコア閾値」を設け、閾値未満なら「未判定」と扱うのも有効。
- 返却後は必ずガード(0ならエラー扱い)+ログ出力で原因特定をしやすく。
型別テンプレ:電話番号・日付・金額などの特徴で判定
用途別に特徴量を変えると精度が上がります。
Function ScorePhoneColumn(ByVal ws As Worksheet, ByVal c As Long, ByVal startRow As Long, ByVal endRow As Long) As Long
Dim r As Long, score As Long
For r = startRow To endRow
Dim s As String: s = CStr(ws.Cells(r, c).Value)
If Len(s) = 0 Then GoTo NextRow
' 数字+ハイフン可、数字抽出後10-11桁が望ましい
Dim digits As String: digits = ExtractDigits(s)
If Len(digits) >= 10 And Len(digits) <= 11 And digits Like "*[!0-9]*" = False Then
score = score + 3
Else
score = score - 1
End If
NextRow:
Next
ScorePhoneColumn = score
End Function
Private Function ExtractDigits(ByVal s As String) As String
Dim i As Long, r As String
For i = 1 To Len(s)
Dim ch As String: ch = Mid$(s, i, 1)
If ch Like "[0-9]" Then r = r & ch
Next
ExtractDigits = r
End Function
VB- 深掘り: 型に合わせて「期待桁数」「文字種」を評価する。日付なら
IsDateを使って加点、金額なら「カンマ除去→IsNumeric→範囲」などを織り込む。
ヘッダー行が不明な時:上から数行を走査して推定
実務ではヘッダー行が1行目とは限りません。見出し行を自動で見つけます。
Function DetectHeaderRow(ByVal ws As Worksheet, ByVal maxCheckRows As Long) As Long
Dim r As Long, c As Long, lastCol As Long
For r = 1 To maxCheckRows
lastCol = ws.Cells(r, ws.Columns.Count).End(xlToLeft).Column
Dim headerCount As Long: headerCount = 0
For c = 1 To lastCol
Dim s As String: s = CStr(ws.Cells(r, c).Value)
' ヘッダーっぽい条件例:文字のみ・短い・記号少なめ
If Len(s) > 0 And Len(s) <= 20 And s Like "*[A-Za-z0-9ぁ-んァ-ン一-龥]*" Then
headerCount = headerCount + 1
End If
Next
If headerCount >= WorksheetFunction.Max(1, lastCol \ 2) Then
DetectHeaderRow = r
Exit Function
End If
Next
DetectHeaderRow = 1 ' フォールバック
End Function
VB- 深掘り: 「ヘッダーっぽさ」をルールで判定。厳密ではないが、可変フォーマットに対して自動調整の入口になります。決め打ちと併用がベスト。
例題で練習(貼って試せる)
- 例1(完全一致): ヘッダー「社員番号」で列を取得し、該当列にフラグを書き込む。
- 例2(同義語): ヘッダーが「社員ID」でも検出されるか確認。
- 例3(型スコア): 6桁整数の社員番号列を推定し、結果を表示。
- 例4(電話列): ハイフン混在の電話列をスコア判定し、最もスコアが高い列を選ぶ。
- 例5(ヘッダー自動検出): 上から5行走査し、見出し行を推定→その行で列検出。
実務の落とし穴と対策(重要ポイント)
- 落とし穴1:誤検知で別列を処理してしまう
- 対策: ヘッダー+型スコアの併用、最低スコア閾値、検出結果を一度メッセージで確認・ログ記録。
- 落とし穴2:空データや混在データでスコアが偏る
- 対策: サンプル行数を増やす・欠損はスコアに影響しすぎないように設計(0点扱い等)。
- 落とし穴3:列数が非常に多いと遅い
- 対策: ヘッダー候補で列を絞ってから型スコアを適用。配列で一括読み(Value2)で高速化。
- 落とし穴4:表記ゆれ(漢字/カナ/英語)
- 対策: 同義語を十分に用意、部分一致にする、正規化(全角→半角・Trim)をヘッダーに適用。
- 落とし穴5:ヘッダー行が変動
- 対策: DetectHeaderRowで推定し、確信度が低い場合はユーザーに確認ダイアログ(運用設計で補う)。
スターター手順
- 完全一致の基本関数(FindColumnByHeader)でヘッダー列取得を体感。
- 同義語・部分一致(FindColumnByAliases)で表記ゆれ耐性を追加。
- 型スコア(AutoDetectColumn)で信頼度を上げる。
- ヘッダー自動検出(DetectHeaderRow)を組み合わせ、可変フォーマットへ対応。
- 結果ガード+ログを必ず入れて、誤検知時にすぐ気づける仕組みを整える。
