ARTICLE · 1119685
第07讲:If条件判断:让Excel根据规则自主决策
第07讲:If条件判断:让Excel根据规则自主决策

痛点拆解
现实场景:
销售提成规则:5万以下3%,5-10万5%,10-20万8%,20万以上10% Excel公式: =IF(A2<50000,A2*0.03,IF(A2<100000,A2*0.05,IF(A2<200000,A2*0.08,A2*0.1)))问题:嵌套4层,修改规则需重新写公式,容易出错
VBA解决方案:用结构化代码替代嵌套公式,逻辑清晰,易于维护
1. If条件判断的四种结构
1.1 单行If(简单判断)
Option ExplicitSub SingleLineIf() '==================================================== ' 功能:演示单行If语句(不需要End If) ' 场景:简单的二选一判断 '==================================================== Dim score As Long Dim result As String score = 85 ' 单行格式:If 条件 Then 执行语句 If score >= 60 Then result = "及格" Debug.Print result ' 输出:及格 ' 多条语句用冒号分隔(不推荐,影响可读性) If score >= 90 Then result = "优秀": Debug.Print "奖励100元"End Sub1.2 标准If...Then...End If(单分支)
Option ExplicitSub StandardIf() '==================================================== ' 功能:演示标准If结构(单分支判断) ' 场景:满足条件才执行操作 '==================================================== Dim sales As Double Dim bonus As Double sales = 120000 bonus = 0 ' 标准格式(多行) If sales > 100000 Then bonus = sales * 0.05 Debug.Print "超额完成任务" Debug.Print "奖金:" & bonus End If ' 不满足条件时不执行任何操作 If sales < 50000 Then Debug.Print "未达成基本目标" End IfEnd Sub1.3 If...Then...Else(双分支)
Option ExplicitSub IfElseDemo() '==================================================== ' 功能:演示If...Else结构(二选一) ' 场景:根据条件执行不同操作 '==================================================== Dim age As Long Dim category As String age = 25 If age >= 18 Then category = "成年人" Debug.Print "可以投票" Else category = "未成年人" Debug.Print "不可以投票" End If Debug.Print "分类:" & category ' 实际应用:判断单元格是否为空 If IsEmpty(Range("A1").Value) Then Range("A1").Value = "默认值" Range("A1").Interior.Color = RGB(255, 255, 0) Else Debug.Print "A1已有数据:" & Range("A1").Value End IfEnd Sub1.4 If...ElseIf...Else(多分支)
Option ExplicitSub IfElseIfDemo() '==================================================== ' 功能:演示多分支判断(替代嵌套If) ' 场景:多个条件分级判断 '==================================================== Dim score As Long Dim grade As String score = 85 ' 多分支结构(从上到下依次判断,匹配第一个即停止) If score >= 90 Then grade = "A" ElseIf score >= 80 Then grade = "B" ElseIf score >= 70 Then grade = "C" ElseIf score >= 60 Then grade = "D" Else grade = "F" End If Debug.Print "分数:" & score & ",等级:" & grade ' 等价的嵌套If(不推荐,难以阅读) If score >= 90 Then grade = "A" Else If score >= 80 Then grade = "B" Else If score >= 70 Then grade = "C" Else If score >= 60 Then grade = "D" Else grade = "F" End If End If End If End IfEnd Sub2. 四种结构对比表
If 条件 Then 语句 | ||||
If 条件 Then 语句End If | ||||
If 条件 Then 语句1Else 语句2End If | ||||
If 条件1 Then 语句1ElseIf 条件2 Then 语句2Else 语句3End If |
3. 复杂逻辑运算:And、Or、Not
3.1 And运算(所有条件都为True)
Option ExplicitSub AndLogicDemo() '==================================================== ' 功能:演示And逻辑运算(与运算) ' 规则:所有条件都为True时,结果才为True '==================================================== Dim age As Long Dim hasLicense As Boolean Dim canDrive As Boolean age = 20 hasLicense = True ' And运算:两个条件都满足 If age >= 18 And hasLicense = True Then canDrive = True Debug.Print "可以驾驶" Else canDrive = False Debug.Print "不可以驾驶" End If ' 实际应用:判断数值范围 Dim score As Long score = 85 If score >= 80 And score < 90 Then Debug.Print "良好(80-89分)" End If ' 多个条件组合 Dim sales As Double Dim attendance As Long Dim performance As String sales = 150000 attendance = 22 If sales > 100000 And attendance >= 20 And performance <> "差" Then Debug.Print "符合晋升条件" End IfEnd SubAnd运算真值表:
3.2 Or运算(任一条件为True)
Option ExplicitSub OrLogicDemo() '==================================================== ' 功能:演示Or逻辑运算(或运算) ' 规则:任一条件为True时,结果就为True '==================================================== Dim isWeekend As Boolean Dim isHoliday As Boolean Dim canRest As Boolean isWeekend = False isHoliday = True ' Or运算:任一条件满足即可 If isWeekend Or isHoliday Then canRest = True Debug.Print "可以休息" Else canRest = False Debug.Print "需要工作" End If ' 实际应用:判断异常数据 Dim value As Double value = -5 If value < 0 Or value > 100 Then Debug.Print "数据异常:" & value End If ' 多条件组合 Dim level As String level = "VIP" If level = "VIP" Or level = "SVIP" Or level = "钻石会员" Then Debug.Print "享受优惠" End IfEnd SubOr运算真值表:
3.3 Not运算(取反)
Option ExplicitSub NotLogicDemo() '==================================================== ' 功能:演示Not逻辑运算(非运算) ' 规则:反转布尔值 '==================================================== Dim isLocked As Boolean isLocked = True ' Not运算:取反 If Not isLocked Then Debug.Print "文件未锁定,可以编辑" Else Debug.Print "文件已锁定" End If ' 实际应用:判断单元格非空 If Not IsEmpty(Range("A1").Value) Then Debug.Print "A1有数据" End If ' 与And组合使用 Dim age As Long Dim isStudent As Boolean age = 25 isStudent = False If age >= 18 And Not isStudent Then Debug.Print "成年且非学生" End IfEnd SubNot运算真值表:
3.4 复合逻辑运算(And、Or、Not混合)
Option ExplicitSub ComplexLogicDemo() '==================================================== ' 功能:演示复合逻辑运算 ' 场景:复杂的业务规则判断 '==================================================== Dim age As Long Dim income As Double Dim hasDebt As Boolean Dim creditScore As Long Dim canLoan As Boolean age = 30 income = 8000 hasDebt = False creditScore = 750 ' 复合条件:(年龄18-60) AND (收入>5000) AND (无债务 OR 信用分>700) If (age >= 18 And age <= 60) And _ income > 5000 And _ (Not hasDebt Or creditScore > 700) Then canLoan = True Debug.Print "符合贷款条件" Else canLoan = False Debug.Print "不符合贷款条件" End If ' 运算符优先级:Not > And > Or ' 建议:用括号明确优先级 Dim a As Boolean, b As Boolean, c As Boolean a = True b = False c = True ' 不加括号(按默认优先级) Debug.Print a Or b And c ' 结果:True(先算b And c) ' 加括号(明确意图) Debug.Print (a Or b) And c ' 结果:TrueEnd Sub运算符优先级表:
() | ||
Not | ||
And | ||
Or |
4. 比较运算符完整列表
= | 5 = 5 | ||
<> | 5 <> 3 | ||
> | 5 > 3 | ||
< | 5 < 3 | ||
>= | 5 >= 5 | ||
<= | 5 <= 3 | ||
Like | "abc" Like "a*" | ||
Is | ws1 Is ws2 |
Option ExplicitSub ComparisonOperatorsDemo() '==================================================== ' 功能:演示比较运算符 '==================================================== Dim num1 As Long, num2 As Long num1 = 10 num2 = 20 Debug.Print "10 = 20 ? " & (num1 = num2) ' False Debug.Print "10 <> 20 ? " & (num1 <> num2) ' True Debug.Print "10 > 20 ? " & (num1 > num2) ' False Debug.Print "10 < 20 ? " & (num1 < num2) ' True Debug.Print "10 >= 20 ? " & (num1 >= num2) ' False Debug.Print "10 <= 20 ? " & (num1 <= num2) ' True ' Like运算符(模糊匹配) Dim name As String name = "张三" If name Like "张*" Then Debug.Print "姓张" End If If name Like "*三" Then Debug.Print "名字含'三'" End If ' Is运算符(对象比较) Dim ws1 As Worksheet, ws2 As Worksheet Set ws1 = Sheets(1) Set ws2 = Sheets(1) If ws1 Is ws2 Then Debug.Print "指向同一个工作表" End IfEnd Sub5. Select Case:多分支的优雅替代
5.1 Select Case基本语法
Option ExplicitSub SelectCaseDemo() '==================================================== ' 功能:演示Select Case结构 ' 优势:比多层If...ElseIf更清晰 '==================================================== Dim score As Long Dim grade As String score = 85 ' Select Case结构 Select Case score Case Is >= 90 grade = "A" Case Is >= 80 grade = "B" Case Is >= 70 grade = "C" Case Is >= 60 grade = "D" Case Else grade = "F" End Select Debug.Print "等级:" & gradeEnd Sub5.2 Select Case高级用法
Option ExplicitSub SelectCaseAdvanced() '==================================================== ' 功能:演示Select Case的高级用法 '==================================================== Dim month As Long Dim season As String month = 8 ' 多个值匹配 Select Case month Case 3, 4, 5 season = "春季" Case 6, 7, 8 season = "夏季" Case 9, 10, 11 season = "秋季" Case 12, 1, 2 season = "冬季" Case Else season = "无效月份" End Select Debug.Print month & "月是" & season ' 范围匹配 Dim age As Long Dim ageGroup As String age = 35 Select Case age Case 0 To 12 ageGroup = "儿童" Case 13 To 17 ageGroup = "青少年" Case 18 To 59 ageGroup = "成年人" Case Is >= 60 ageGroup = "老年人" Case Else ageGroup = "无效年龄" End Select Debug.Print age & "岁属于" & ageGroup ' 字符串匹配 Dim department As String Dim budget As Double department = "技术部" Select Case department Case "技术部", "研发部" budget = 1000000 Case "销售部", "市场部" budget = 500000 Case "行政部", "财务部" budget = 200000 Case Else budget = 100000 End Select Debug.Print department & "预算:" & budgetEnd Sub5.3 If vs Select Case对比
选择建议:
单变量多值判断 → 用Select Case 多条件组合判断 → 用If...ElseIf 两个分支 → 用If...Else
6. 实战案例
案例6.1:销售提成计算(梯级奖金)
Option ExplicitSub CalculateCommission() '==================================================== ' 功能:根据销售额计算梯级提成 ' 规则: ' 0-5万:3% ' 5-10万:5% ' 10-20万:8% ' 20万以上:10% '==================================================== Dim ws As Worksheet Dim lastRow As Long Dim i As Long Dim sales As Double Dim commission As Double Dim rate As Double Application.ScreenUpdating = False Set ws = ActiveSheet lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row If lastRow < 2 Then MsgBox "无数据", vbExclamation GoTo CleanUp End If ' 添加表头 ws.Range("C1").Value = "提成比例" ws.Range("D1").Value = "提成金额" ws.Range("C1:D1").Font.Bold = True For i = 2 To lastRow ' 读取销售额 If Not IsNumeric(ws.Cells(i, 2).Value) Then ws.Cells(i, 3).Value = "数据错误" ws.Cells(i, 4).Value = 0 GoTo NextRow End If sales = CDbl(ws.Cells(i, 2).Value) ' 判断提成比例 If sales < 50000 Then rate = 0.03 ElseIf sales < 100000 Then rate = 0.05 ElseIf sales < 200000 Then rate = 0.08 Else rate = 0.1 End If ' 计算提成 commission = sales * rate ' 写入结果 ws.Cells(i, 3).Value = Format(rate, "0.0%") ws.Cells(i, 4).Value = commission ws.Cells(i, 4).NumberFormat = "#,##0.00"NextRow: Next i MsgBox "提成计算完成!共处理 " & (lastRow - 1) & " 条记录", vbInformationCleanUp: Application.ScreenUpdating = True Set ws = NothingEnd Sub案例6.2:多条件评级系统
Option ExplicitSub EmployeeEvaluation() '==================================================== ' 功能:员工绩效评级 ' 规则: ' 销售额>=10万 AND 出勤>=22天 → A级 ' 销售额>=8万 AND 出勤>=20天 → B级 ' 销售额>=5万 AND 出勤>=18天 → C级 ' 其他 → D级 '==================================================== Dim ws As Worksheet Dim lastRow As Long Dim i As Long Dim name As String Dim sales As Double Dim attendance As Long Dim grade As String Dim bonus As Double Application.ScreenUpdating = False Set ws = ActiveSheet lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row If lastRow < 2 Then MsgBox "无数据", vbExclamation GoTo CleanUp End If ' 添加表头 ws.Range("D1").Value = "评级" ws.Range("E1").Value = "奖金" ws.Range("D1:E1").Font.Bold = True For i = 2 To lastRow name = ws.Cells(i, 1).Value ' 数据验证 If Not IsNumeric(ws.Cells(i, 2).Value) Or _ Not IsNumeric(ws.Cells(i, 3).Value) Then ws.Cells(i, 4).Value = "数据错误" ws.Cells(i, 5).Value = 0 GoTo NextRow End If sales = CDbl(ws.Cells(i, 2).Value) attendance = CLng(ws.Cells(i, 3).Value) ' 多条件判断 If sales >= 100000 And attendance >= 22 Then grade = "A" bonus = 5000 ElseIf sales >= 80000 And attendance >= 20 Then grade = "B" bonus = 3000 ElseIf sales >= 50000 And attendance >= 18 Then grade = "C" bonus = 1000 Else grade = "D" bonus = 0 End If ' 写入结果 ws.Cells(i, 4).Value = grade ws.Cells(i, 5).Value = bonus ws.Cells(i, 5).NumberFormat = "#,##0" ' 设置颜色 Select Case grade Case "A" ws.Cells(i, 4).Interior.Color = RGB(146, 208, 80) Case "B" ws.Cells(i, 4).Interior.Color = RGB(255, 230, 153) Case "C" ws.Cells(i, 4).Interior.Color = RGB(255, 192, 0) Case "D" ws.Cells(i, 4).Interior.Color = RGB(255, 0, 0) End SelectNextRow: Next i MsgBox "评级完成!共处理 " & (lastRow - 1) & " 名员工", vbInformationCleanUp: Application.ScreenUpdating = True Set ws = NothingEnd Sub案例6.3:数据清洗(异常值检测)
Option ExplicitSub DataValidation() '==================================================== ' 功能:检测并标记异常数据 ' 规则: ' 年龄<18或>65 → 年龄异常 ' 工资<3000或>50000 → 工资异常 ' 部门不在指定列表 → 部门异常 '==================================================== Dim ws As Worksheet Dim lastRow As Long Dim i As Long Dim name As String Dim age As Variant Dim salary As Variant Dim department As String Dim errors As String Dim errorCount As Long Application.ScreenUpdating = False Set ws = ActiveSheet lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row If lastRow < 2 Then MsgBox "无数据", vbExclamation GoTo CleanUp End If ' 添加表头 ws.Range("E1").Value = "异常说明" ws.Range("E1").Font.Bold = True errorCount = 0 For i = 2 To lastRow errors = "" name = ws.Cells(i, 1).Value age = ws.Cells(i, 2).Value salary = ws.Cells(i, 3).Value department = ws.Cells(i, 4).Value ' 检查年龄 If IsEmpty(age) Then errors = errors & "年龄为空; " ElseIf Not IsNumeric(age) Then errors = errors & "年龄非数值; " ElseIf age < 18 Or age > 65 Then errors = errors & "年龄超出范围(" & age & "); " End If ' 检查工资 If IsEmpty(salary) Then errors = errors & "工资为空; " ElseIf Not IsNumeric(salary) Then errors = errors & "工资非数值; " ElseIf salary < 3000 Or salary > 50000 Then errors = errors & "工资异常(" & salary & "); " End If ' 检查部门 If Trim(department) = "" Then errors = errors & "部门为空; " ElseIf Not (department = "技术部" Or department = "销售部" Or _ department = "行政部" Or department = "财务部") Then errors = errors & "部门不存在(" & department & "); " End If ' 写入异常说明 If errors <> "" Then ws.Cells(i, 5).Value = Left(errors, Len(errors) - 2) ws.Cells(i, 5).Interior.Color = RGB(255, 199, 206) ws.Cells(i, 5).Font.Color = RGB(156, 0, 6) errorCount = errorCount + 1 Else ws.Cells(i, 5).Value = "正常" ws.Cells(i, 5).Interior.Color = RGB(198, 239, 206) ws.Cells(i, 5).Font.Color = RGB(0, 97, 0) End If Next i MsgBox "数据验证完成!" & vbCrLf & _ "总记录数:" & (lastRow - 1) & vbCrLf & _ "异常记录:" & errorCount & vbCrLf & _ "正常记录:" & (lastRow - 1 - errorCount), vbInformationCleanUp: Application.ScreenUpdating = True Set ws = NothingEnd Sub案例6.4:会员等级折扣计算
Option ExplicitSub MemberDiscountCalculation() '==================================================== ' 功能:根据会员等级和消费金额计算折扣 ' 规则: ' 普通会员:消费<500不折扣,>=500打9折 ' 银卡会员:消费<500打9.5折,>=500打8.5折 ' 金卡会员:消费<500打9折,>=500打8折 ' 钻石会员:消费<1000打8.5折,>=1000打7折 '==================================================== Dim ws As Worksheet Dim lastRow As Long Dim i As Long Dim memberLevel As String Dim amount As Double Dim discount As Double Dim finalAmount As Double Application.ScreenUpdating = False Set ws = ActiveSheet lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row If lastRow < 2 Then MsgBox "无数据", vbExclamation GoTo CleanUp End If ' 添加表头 ws.Range("D1").Value = "折扣率" ws.Range("E1").Value = "实付金额" ws.Range("D1:E1").Font.Bold = True For i = 2 To lastRow memberLevel = ws.Cells(i, 2).Value If Not IsNumeric(ws.Cells(i, 3).Value) Then ws.Cells(i, 4).Value = "金额错误" ws.Cells(i, 5).Value = 0 GoTo NextRow End If amount = CDbl(ws.Cells(i, 3).Value) ' 根据会员等级和金额判断折扣 Select Case memberLevel Case "普通会员" If amount < 500 Then discount = 1 Else discount = 0.9 End If Case "银卡会员" If amount < 500 Then discount = 0.95 Else discount = 0.85 End If Case "金卡会员" If amount < 500 Then discount = 0.9 Else discount = 0.8 End If Case "钻石会员" If amount < 1000 Then discount = 0.85 Else discount = 0.7 End If Case Else discount = 1 memberLevel = "未知等级" End Select ' 计算实付金额 finalAmount = amount * discount ' 写入结果 ws.Cells(i, 4).Value = Format(discount, "0.0%") ws.Cells(i, 5).Value = finalAmount ws.Cells(i, 5).NumberFormat = "#,##0.00" ' 高亮优惠金额 If discount < 1 Then ws.Cells(i, 5).Font.Color = RGB(255, 0, 0) ws.Cells(i, 5).Font.Bold = True End IfNextRow: Next i MsgBox "折扣计算完成!共处理 " & (lastRow - 1) & " 笔订单", vbInformationCleanUp: Application.ScreenUpdating = True Set ws = NothingEnd Sub案例6.5:考勤异常判定
Option ExplicitSub AttendanceCheck() '==================================================== ' 功能:判定考勤异常类型 ' 规则: ' 迟到:09:00后到,扣50元 ' 早退:17:30前走,扣50元 ' 旷工:未打卡,扣200元 ' 加班:19:00后走,奖励100元 '==================================================== Dim ws As Worksheet Dim lastRow As Long Dim i As Long Dim name As String Dim clockIn As Variant Dim clockOut As Variant Dim status As String Dim penalty As Long Dim standardIn As Date Dim standardOut As Date Dim overtimeThreshold As Date Application.ScreenUpdating = False Set ws = ActiveSheet lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row If lastRow < 2 Then MsgBox "无数据", vbExclamation GoTo CleanUp End If ' 设置标准时间 standardIn = TimeValue("09:00:00") standardOut = TimeValue("17:30:00") overtimeThreshold = TimeValue("19:00:00") ' 添加表头 ws.Range("D1").Value = "状态" ws.Range("E1").Value = "扣款/奖励" ws.Range("D1:E1").Font.Bold = True For i = 2 To lastRow name = ws.Cells(i, 1).Value clockIn = ws.Cells(i, 2).Value clockOut = ws.Cells(i, 3).Value status = "正常" penalty = 0 ' 检查上班打卡 If IsEmpty(clockIn) Then status = "旷工(未打卡)" penalty = -200 ElseIf IsDate(clockIn) Then If TimeValue(clockIn) > standardIn Then status = "迟到" penalty = -50 End If End If ' 检查下班打卡 If IsEmpty(clockOut) Then If status = "正常" Then status = "未打下班卡" Else status = status & " + 未打下班卡" End If ElseIf IsDate(clockOut) Then If TimeValue(clockOut) < standardOut Then If status = "正常" Then status = "早退" penalty = -50 Else status = status & " + 早退" penalty = penalty - 50 End If ElseIf TimeValue(clockOut) > overtimeThreshold Then If status = "正常" Then status = "加班" penalty = 100 End If End If End If ' 写入结果 ws.Cells(i, 4).Value = status ws.Cells(i, 5).Value = penalty ' 设置颜色 If penalty < 0 Then ws.Cells(i, 4).Interior.Color = RGB(255, 199, 206) ws.Cells(i, 5).Font.Color = RGB(255, 0, 0) ElseIf penalty > 0 Then ws.Cells(i, 4).Interior.Color = RGB(198, 239, 206) ws.Cells(i, 5).Font.Color = RGB(0, 128, 0) Else ws.Cells(i, 4).Interior.Color = RGB(255, 255, 255) End If Next i MsgBox "考勤检查完成!共处理 " & (lastRow - 1) & " 条记录", vbInformationCleanUp: Application.ScreenUpdating = True Set ws = NothingEnd Sub7. 快速决策流程图
需要条件判断 ↓几个分支? ├─ 1个 → If...Then...End If ├─ 2个 → If...Then...Else...End If └─ 3个以上 → 是否单变量多值判断? ├─ 是 → Select Case └─ 否 → If...ElseIf...Else...End If条件复杂吗? ├─ 简单(一个条件) → 直接判断 └─ 复杂 → 需要And/Or组合吗? ├─ 所有条件都满足 → 用And ├─ 任一条件满足 → 用Or └─ 取反 → 用Not8. 常见错误与解决方案
9. 最佳实践检查清单
[ ] 多于3个分支时,优先考虑Select Case [ ] 复杂条件用括号明确优先级 [ ] 数值范围判断从小到大或从大到小排列 [ ] 用IsNumeric()、IsEmpty()验证数据类型 [ ] 不要嵌套超过3层If [ ] 关键判断后加注释说明业务规则 [ ] 每个If必须有对应的End If [ ] Select Case必须有Case Else兜底
