You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Excel/VBA:按姓名匹配查找行并分列统计非空值求助

用VBA实现姓名对应列的非空条目统计

你这个需求用For Each循环完全可以实现,我给你整理了完整的代码和详细解释,你可以直接套用,还附带了后续加权求和的扩展方案~

核心思路

  1. 遍历Sheet1中A列的每个姓名
  2. 对每个姓名,在Sheet2中找到所有匹配的行
  3. 分别统计这些行中B、C、D列的非空单元格数量
  4. 将统计结果写入Sheet1对应行的后续列,方便后续加权计算

完整VBA代码

Sub CountNonEmptyEntries()
    ' 定义工作表对象
    Dim ws1 As Worksheet, ws2 As Worksheet
    ' 定义遍历用的单元格变量
    Dim nameCell As Range, cell2 As Range
    ' 存储最后一行行号
    Dim lastRow1 As Long, lastRow2 As Long
    ' 存储各列非空计数
    Dim countB As Integer, countC As Integer, countD As Integer
    
    ' 指定工作表(如果你的表名不是Sheet1/Sheet2,记得修改)
    Set ws1 = ThisWorkbook.Sheets("Sheet1")
    Set ws2 = ThisWorkbook.Sheets("Sheet2")
    
    ' 获取两个工作表中A列的最后一行(避免遍历空行)
    lastRow1 = ws1.Cells(ws1.Rows.Count, "A").End(xlUp).Row
    lastRow2 = ws2.Cells(ws2.Rows.Count, "A").End(xlUp).Row
    
    ' 遍历Sheet1中A列的所有姓名(从A2开始,假设A1是表头)
    For Each nameCell In ws1.Range("A2:A" & lastRow1)
        ' 每次遍历新姓名前,重置计数器
        countB = 0
        countC = 0
        countD = 0
        
        ' 遍历Sheet2中A列的所有姓名(同样假设A1是表头)
        For Each cell2 In ws2.Range("A2:A" & lastRow2)
            ' 找到匹配的姓名
            If cell2.Value = nameCell.Value Then
                ' 检查B列是否非空(排除纯空格的情况可以用 Len(Trim(cell2.Offset(0,1).Value)) > 0)
                If Not IsEmpty(cell2.Offset(0, 1)) Then countB = countB + 1
                ' 检查C列
                If Not IsEmpty(cell2.Offset(0, 2)) Then countC = countC + 1
                ' 检查D列
                If Not IsEmpty(cell2.Offset(0, 3)) Then countD = countD + 1
            End If
        Next cell2
        
        ' 将统计结果写入Sheet1的B、C、D列(可根据需求调整列位置)
        nameCell.Offset(0, 1) = countB
        nameCell.Offset(0, 2) = countC
        nameCell.Offset(0, 3) = countD
        
        ' ---------------------- 可选:直接计算加权求和结果 ----------------------
        ' 假设B列权重0.3,C列0.5,D列0.2,结果写入E列
        ' nameCell.Offset(0, 4) = countB * 0.3 + countC * 0.5 + countD * 0.2
    Next nameCell
    
    MsgBox "统计完成!", vbInformation
End Sub

代码关键部分解释

  • 工作表与行号处理:先获取两个表的最后一行,避免遍历大量空行,提升效率
  • 双层For Each循环:外层遍历Sheet1的姓名,内层遍历Sheet2找匹配项,完全符合你想要的循环逻辑
  • 非空判断:用IsEmpty检查单元格是否为空,如果要排除仅含空格的单元格,可以替换成Len(Trim(cell2.Offset(0,1).Value)) > 0
  • 结果写入:用Offset方法定位到当前姓名行的后续列,把统计值写入,方便后续处理

注意事项

  • 如果Sheet2中的姓名不在A列,建议改用行号定位的方式,避免偏移出错。比如姓名在F列,内层循环可以改成:
    For Each cell2 In ws2.Range("F2:F" & lastRow2)
        If cell2.Value = nameCell.Value Then
            If Not IsEmpty(ws2.Cells(cell2.Row, "B")) Then countB = countB + 1
            If Not IsEmpty(ws2.Cells(cell2.Row, "C")) Then countC = countC + 1
            If Not IsEmpty(ws2.Cells(cell2.Row, "D")) Then countD = countD + 1
        End If
    Next cell2
    
  • 如果数据量极大,双层循环效率偏低,可以改用Find方法批量查找匹配项,减少遍历次数,不过对于常规数据量,双层循环完全够用。

内容的提问来源于stack exchange,提问作者quantumspores

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:41:37