複雑な条件は「一気に全部を判定しない」ことがコツです。大事なのは分割・標準化・見える化。条件を小さく切って順番に確定し、最後に組み合わせて結果を出すと、初心者でも迷わず書けます。
基本戦略(これだけ覚えれば大丈夫)
- 分割: 大きな判定を、意味のある小さな判断に分ける
- 標準化: 比較前に文字や数値の形式をそろえる(大小・空白・範囲)
- 早期終了: 想定外やエラーは最初に弾いて、後続の条件をシンプルにする
- 段階化: 「軸ごと」に判定を進める(例:カテゴリ→金額→方法)
- 見える化: ルールを表や関数に移し、コードの分岐を減らす
例1: 巨大な If を「分割+段階化」で読みやすく
シナリオ
「会員種別 × 金額 × 支払い方法」で手数料を決める。最初は If の海になりがちです。
改善後(Select Case+段階化)
Function CalcFee(memberType As String, amount As Currency, pay As String) As Currency
' 標準化(大小・空白)
memberType = UCase(Trim(memberType))
pay = UCase(Trim(pay))
' 早期終了(エラー・想定外)
If amount <= 0 Then CalcFee = 0: Exit Function
If pay <> "CARD" And pay <> "CASH" Then CalcFee = 1000: Exit Function
' 段階化(金額帯を先に決める)
Dim band As String
If amount >= 100000 Then
band = "HIGH"
ElseIf amount >= 20000 Then
band = "MID"
Else
band = "LOW"
End If
' 外側:会員種別ごとのルールブロック
Select Case UCase(memberType)
Case "VIP"
Select Case band
Case "HIGH": CalcFee = IIf(pay = "CARD", 0, 200)
Case "MID": CalcFee = IIf(pay = "CARD", 100, 300)
Case "LOW": CalcFee = IIf(pay = "CARD", 200, 400)
End Select
Case "REG"
Select Case band
Case "HIGH": CalcFee = IIf(pay = "CARD", 300, 500)
Case "MID": CalcFee = IIf(pay = "CARD", 400, 600)
Case "LOW": CalcFee = IIf(pay = "CARD", 500, 700)
End Select
Case Else
CalcFee = 1000
End Select
End Function
VB- ポイント:
- 標準化で比較ミスを減らす。
- 早期終了で不正値の枝を消す。
- 金額帯の段階化で内側の条件を簡潔にする。
例2: 「ひとつのキー」にまとめてフラット化
シナリオ
二段・三段のネストが長くなってきたら、前処理で「キー化」して1段の Select Case にします。
Function ShippingRule(region As String, weight As Double) As String
region = UCase(Trim(region))
' ガード節
If weight <= 0 Then ShippingRule = "重量不正": Exit Function
' キー化(組み合わせをひとつの値に)
Dim weightBand As String
If weight < 1 Then
weightBand = "LIGHT"
ElseIf weight < 5 Then
weightBand = "MED"
Else
weightBand = "HEAVY"
End If
Dim key As String
key = region & "_" & weightBand
Select Case key
Case "LOCAL_LIGHT": ShippingRule = "当日配達"
Case "LOCAL_MED": ShippingRule = "翌日配達"
Case "LOCAL_HEAVY": ShippingRule = "通常配達"
Case "REMOTE_LIGHT": ShippingRule = "航空便"
Case "REMOTE_MED": ShippingRule = "船便"
Case "REMOTE_HEAVY": ShippingRule = "大型貨物"
Case Else: ShippingRule = "ルール未定義"
End Select
End Function
VB- メリット:
- 1段で完結して見通しが良い。
- 組み合わせ追加が容易(Caseの行を増やすだけ)。
例3: ルールの「表」を使う(見える化)
シナリオ
条件が増えるほどコードが長くなる。ルールをワークシートに置いて、検索して使う方法。
' ルール表(シート "Rules")
' A:会員種別 B:金額帯 C:支払い方法 D:手数料
' 例: VIP | HIGH | CARD | 0
Function LookupFee(memberType As String, band As String, pay As String) As Currency
Dim ws As Worksheet, lastRow As Long, i As Long
Set ws = ThisWorkbook.Worksheets("Rules")
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
memberType = UCase(Trim(memberType))
band = UCase(Trim(band))
pay = UCase(Trim(pay))
For i = 2 To lastRow ' ヘッダ行を除く
If ws.Cells(i, "A").Value = memberType _
And ws.Cells(i, "B").Value = band _
And ws.Cells(i, "C").Value = pay Then
LookupFee = ws.Cells(i, "D").Value
Exit Function
End If
Next i
LookupFee = 1000 ' 未定義はデフォルト
End Function
VB- ポイント:
- 業務ルールを表に移すと、コード変更なしで運用側が更新できる。
- テストが楽(表を差し替えるだけ)。
例4: 真理値(True/False)を先に確定する
シナリオ
複雑な条件式は、意味のある「真偽フラグ」に分解してから組み立てる。
Function CanApplyCoupon(isMember As Boolean, isFirstPurchase As Boolean, amount As Currency, hasSpecialSale As Boolean) As Boolean
' フラグ分解
Dim enoughAmount As Boolean: enoughAmount = (amount >= 5000)
Dim specialOK As Boolean: specialOK = (hasSpecialSale = False)
' 早期終了
If Not isMember Then CanApplyCoupon = False: Exit Function
' 組み立て(読みやすい論理式)
CanApplyCoupon = (isFirstPurchase Or specialOK) And enoughAmount
End Function
VB- メリット:
- 長い条件式でも意味の単位で読める。
- テストしやすい(フラグごとに検証)。
例5: 入力の標準化とガード節
シナリオ
文字入力に揺らぎ(全角・半角・大小・空白)があると条件ミスが起きる。
Function ParseDept(rawDept As String) As String
Dim dept As String
dept = UCase(Trim(rawDept)) ' 余白・大小を統一
dept = Replace(dept, " ", "") ' 全角スペース除去
dept = Replace(dept, "DEPT-", "") ' 接頭辞を除去
Select Case dept
Case "SALES": ParseDept = "営業"
Case "HR": ParseDept = "人事"
Case "IT": ParseDept = "情報システム"
Case Else: ParseDept = "不明"
End Select
End Function
VB- ポイント:
- 比較前の前処理で条件分岐を安定化。
- 仕様変更に強い(前処理を直せば判定が保てる)。
よくあるつまずきと解決
- 重なる範囲が混乱する:
狭い条件→広い条件の順に並べる。Case Else は最後。 - ネストが深くなりすぎる:
キー化して1段にする、または表に移す。 - 同じ処理が重複:
補助関数に切り出して再利用する。 - 可読性が落ちる論理式:
真偽フラグに分解してから組み立てる。 - 入力の揺らぎで誤判定:
Trim/UCase/Replaceで標準化してから比較。
小さな練習課題
- 課題1: 「地域 × 会員種別 × 金額帯」でポイント倍率を返す関数。キー化でフラットに書いてください。
- 課題2: 返品ルールをシートに表で作り、カテゴリ・日数・状態(未開封/開封済)で可否を検索する関数を書いてください。
- 課題3: 入力文字列の正規化(余白・全角記号・大小)を行う補助関数 Normalize を作り、他の判定関数から必ず呼ぶようにしてください。
小さな練習課題の解答と解説
課題1: 「地域 × 会員種別 × 金額帯」でポイント倍率を返す関数(キー化でフラット化)
解答例
Function GetPointRate(region As String, memberType As String, amount As Currency) As Double
region = UCase(Trim(region))
memberType = UCase(Trim(memberType))
' 金額帯を先に決める
Dim band As String
If amount >= 100000 Then
band = "HIGH"
ElseIf amount >= 50000 Then
band = "MID"
Else
band = "LOW"
End If
' キー化(組み合わせをひとつの文字列に)
Dim key As String
key = region & "_" & memberType & "_" & band
Select Case key
Case "TOKYO_VIP_HIGH": GetPointRate = 3
Case "TOKYO_VIP_MID": GetPointRate = 2
Case "TOKYO_VIP_LOW": GetPointRate = 1
Case "TOKYO_REG_HIGH": GetPointRate = 2
Case "TOKYO_REG_MID": GetPointRate = 1.5
Case "TOKYO_REG_LOW": GetPointRate = 1
Case Else: GetPointRate = 0.5 ' デフォルト
End Select
End Function
VB解説
- 金額帯を先に分類して「HIGH/MID/LOW」に。
- キー化で「地域会員種別金額帯」というひとつの文字列にまとめる。
- Select Caseは1段で済み、見通しが良くなる。
課題2: 返品ルールをシートに表で作り、カテゴリ・日数・状態で可否を検索
解答例
(シート “ReturnRules” にルール表を作成:A列=カテゴリ、B列=日数上限、C列=状態、D列=可否)
Function CanReturn(category As String, days As Integer, status As String) As String
Dim ws As Worksheet, lastRow As Long, i As Long
Set ws = ThisWorkbook.Worksheets("ReturnRules")
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
category = UCase(Trim(category))
status = UCase(Trim(status))
For i = 2 To lastRow ' ヘッダを除く
If ws.Cells(i, "A").Value = category _
And days <= ws.Cells(i, "B").Value _
And ws.Cells(i, "C").Value = status Then
CanReturn = ws.Cells(i, "D").Value
Exit Function
End If
Next i
CanReturn = "ルール未定義"
End Function
VB解説
- ルールをシートに置くことで、コードを変更せずに運用側が更新可能。
- 検索ループで一致条件を探し、可否を返す。
- days <= 上限で日数判定を行う。
課題3: 入力文字列の正規化(余白・全角記号・大小)を行う補助関数 Normalize
解答例
Function Normalize(text As String) As String
Dim result As String
result = Trim(text) ' 前後の空白除去
result = Replace(result, " ", "") ' 全角スペース除去
result = UCase(result) ' 大文字に統一
Normalize = result
End Function
' 使用例
Function ParseDept(rawDept As String) As String
Dim dept As String
dept = Normalize(rawDept)
Select Case dept
Case "SALES": ParseDept = "営業"
Case "HR": ParseDept = "人事"
Case "IT": ParseDept = "情報システム"
Case Else: ParseDept = "不明"
End Select
End Function
VB解説
- Normalize関数で入力を標準化。
- Trim/UCase/Replaceを組み合わせて揺らぎを吸収。
- 他の判定関数から必ず呼び出すことで、条件分岐が安定する。
