vba学习系列(11)--批退率&通过率等数据分析

发布于:2025-06-15 ⋅ 阅读:(15) ⋅ 点赞:(0)

系列文章目录

前言

一、外观报表

1.产能


Sub ProcessInspectionData()
    Dim ws1 As Worksheet, ws2 As Worksheet, ws3 As Worksheet
    Dim lastRow1 As Long, lastRow3 As Long
    Dim dateCol As Range, empRange As Range
    Dim i As Long, j As Long, k As Long
    Dim count As Long, holeCount As Long
    Dim okHoles As String, ngHoles As String
    Dim inspector As String, checkDate As Date
    
    ' 初始化工作表对象
    Set ws1 = ThisWorkbook.Sheets("镜片抽检履历")
    Set ws2 = ThisWorkbook.Sheets("人员产能")
    Set ws3 = ThisWorkbook.Sheets("镜筒抽检履历")
    
    ' 清除原有数据
    ws2.Range("F3:AJ82").ClearContents
    
    ' 获取日期列范围
    Set dateCol = ws2.Range("F2:AJ2")
    
    ' 处理镜片抽检履历(Sheet1)
    lastRow1 = ws1.Cells(ws1.Rows.count, "B").End(xlUp).Row
    For i = 4 To lastRow1
        checkDate = ws1.Cells(i, "B").value
        inspector = ws1.Cells(i, "O").value
        okHoles = ws1.Cells(i, "J").value
        ngHoles = ws1.Cells(i, "K").value
        
        ' 计算穴号总数
        holeCount = CountHoles(okHoles) + CountHoles(ngHoles)
        
        ' 查找匹配的日期列
        For j = 1 To dateCol.Columns.count
            If dateCol.Cells(1, j).value = checkDate Then
                ' 情况1: J列和K列均为空
                If okHoles = "" And ngHoles = "" Then
                    Set empRange = ws2.Range("D3:D22")
                    For k = 1 To empRange.Rows.count
                        If empRange.Cells(k, 1).value = inspector Then
                            ws2.Cells(k + 2, j + 5).value = Nz(ws2.Cells(k + 2, j + 5).value) + 3
                            Exit For
                        End If
                    Next k
                ' 情况2: 有穴号但总数<3
                ElseIf holeCount > 0 And holeCount < 3 Then
                    Set empRange = ws2.Range("D23:D42")
                    For k = 1 To empRange.Rows.count
                        If empRange.Cells(k, 1).value = inspector Then
                            ws2.Cells(k + 22, j + 5).value = Nz(ws2.Cells(k + 22, j + 5).value) + 3
                            Exit For
                        End If
                    Next k
                ' 情况3: 有穴号且总数>=3
                ElseIf holeCount >= 3 Then
                    Set empRange = ws2.Range("D23:D42")
                    For k = 1 To empRange.Rows.count
                        If empRange.Cells(k, 1).value = inspector Then
                            ws2.Cells(k + 22, j + 5).value = Nz(ws2.Cells(k + 22, j + 5).value) + holeCount
                            Exit For
                        End If
                    Next k
                End If
                Exit For
            End If
        Next j
    Next i
    
    ' 处理镜筒抽检履历(Sheet3)
    lastRow3 = ws3.Cells(ws3.Rows.count, "B").End(xlUp).Row
    For i = 4 To lastRow3
        checkDate = ws3.Cells(i, "B").value
        inspector = ws3.Cells(i, "N").value
        okHoles = ws3.Cells(i, "I").value
        ngHoles = ws3.Cells(i, "J").value
        
        ' 计算穴号总数
        holeCount = CountHoles(okHoles) + CountHoles(ngHoles)
        
        ' 查找匹配的日期列
        For j = 1 To dateCol.Columns.count
            If dateCol.Cells(1, j).value = checkDate Then
                ' 情况4: 有穴号但总数<3
                If holeCount > 0 And holeCount < 3 Then
                    Set empRange = ws2.Range("D43:D62")
                    For k = 1 To empRange.Rows.count
                        If empRange.Cells(k, 1).value = inspector Then
                            ws2.Cells(k + 42, j + 5).value = Nz(ws2.Cells(k + 42, j + 5).value) + 3
                            Exit For
                        End If
                    Next k
                ' 情况5: 有穴号且总数>=3
                ElseIf holeCount >= 3 Then
                    Set empRange = ws2.Range("D43:D62")
                    For k = 1 To empRange.Rows.count
                        If empRange.Cells(k, 1).value = inspector Then
                            ws2.Cells(k + 42, j + 5).value = Nz(ws2.Cells(k + 42, j + 5).value) + holeCount
                            Exit For
                        End If
                    Next k
                End If
                Exit For
            End If
        Next j
    Next i
    
    ' 计算总和(D63:D82)
    For j = 1 To dateCol.Columns.count
        For k = 1 To 20
            ws2.Cells(k + 62, j + 5).value = _
                Nz(ws2.Cells(k + 2, j + 5).value) + _
                Nz(ws2.Cells(k + 22, j + 5).value) + _
                Nz(ws2.Cells(k + 42, j + 5).value)
            If ws2.Cells(k + 62, j + 5).value = 0 Then
                ws2.Cells(k + 62, j + 5).value = ""
            End If
        Next k
    Next j
    
    MsgBox "产能汇总完成!", vbInformation
End Sub

Function CountHoles(holeStr As String) As Long
    If holeStr = "" Then Exit Function
    CountHoles = UBound(Split(holeStr, "+")) + 1
End Function

Function Nz(value As Variant) As Long
    If IsEmpty(value) Or value = "" Then
        Nz = 0
    Else
        Nz = CLng(value)
    End If
End Function

2.固定伤排查


Sub ExtractAndMarkLensData()
    Dim ws1 As Worksheet, ws2 As Worksheet
    Dim dict As Object, okDict As Object, ngDict As Object
    Dim lastRow As Long, i As Long, j As Long
    Dim startDate As Date, endDate As Date
    Dim outputRow As Long, colIndex As Integer
    Dim key As String, numbers As Variant
    Dim item As Variant, sortedItems(), temp
    
    Application.ScreenUpdating = False
    
    Set ws1 = ThisWorkbook.Sheets("镜片抽检履历")
    Set ws2 = ThisWorkbook.Sheets("固定伤排查")
    
    Set dict = CreateObject("Scripting.Dictionary")
    Set okDict = CreateObject("Scripting.Dictionary")
    Set ngDict = CreateObject("Scripting.Dictionary")
    
    ' 获取日期范围
    On Error Resume Next
    startDate = CDate(ws2.Range("A3").value)
    endDate = CDate(ws2.Range("B3").value)
    On Error GoTo 0
    
    If startDate = 0 Or endDate = 0 Then
        MsgBox "日期格式错误,请检查A3/B3单元格", vbCritical
        Exit Sub
    End If
    
    lastRow = ws1.Cells(ws1.Rows.count, "B").End(xlUp).Row
    ws2.Range("A5:AM" & ws2.Rows.count).ClearContents
    ws2.Range("A5:AM" & ws2.Rows.count).Interior.ColorIndex = xlNone
    
    ' 数据收集阶段
    For i = 4 To lastRow
        Dim currentDate As Date
        currentDate = CDate(ws1.Cells(i, "B").value)
        
        If currentDate >= startDate And currentDate <= endDate Then
            key = ws1.Cells(i, "G").value & "|" & ws1.Cells(i, "H").value & "|" & ws1.Cells(i, "I").value
            
            ' 存储基础数据
            If Not dict.exists(key) Then
                dict.Add key, Array(ws1.Cells(i, "G").value, ws1.Cells(i, "H").value, ws1.Cells(i, "I").value)
            End If
            
            ' 处理OK/NG穴号(优先处理NG)
            ProcessHoleNumbers ws1.Cells(i, "K").value, ngDict, key
            ProcessHoleNumbers ws1.Cells(i, "J").value, okDict, key
        End If
    Next i
    
    ' 将字典项转换为数组并排序(修正下标越界问题)
    If dict.count > 0 Then
        ReDim sortedItems(1 To dict.count)
        i = 1
        For Each item In dict.Items
            sortedItems(i) = item
            i = i + 1
        Next
        
        ' 冒泡排序按H列和I列双重排序
        ' === 三重排序开始 ===
        For i = 1 To UBound(sortedItems) - 1
            For j = i + 1 To UBound(sortedItems)
                ' 第一优先级:H列(机种)
                If sortedItems(i)(1) > sortedItems(j)(1) Then
                    temp = sortedItems(i)
                    sortedItems(i) = sortedItems(j)
                    sortedItems(j) = temp
                ' H列相同时比较I列
                ElseIf sortedItems(i)(1) = sortedItems(j)(1) Then
                    If sortedItems(i)(2) > sortedItems(j)(2) Then
                        temp = sortedItems(i)
                        sortedItems(i) = sortedItems(j)
                        sortedItems(j) = temp
                    ' H列和I列都相同时比较G列
                    ElseIf sortedItems(i)(2) = sortedItems(j)(2) Then
                        If sortedItems(i)(0) > sortedItems(j)(0) Then
                            temp = sortedItems(i)
                            sortedItems(i) = sortedItems(j)
                            sortedItems(j) = temp
                        End If
                    End If
                End If
            Next j
        Next i
        ' === 三重排序结束 ===
    End If
    
    ' 数据输出阶段
    outputRow = 5
    If dict.count > 0 Then
        For i = 1 To UBound(sortedItems)
            key = sortedItems(i)(0) & "|" & sortedItems(i)(1) & "|" & sortedItems(i)(2)
            ws2.Cells(outputRow, "A").Resize(1, 3).value = sortedItems(i)
            
            ' 标记NG穴号(红色,优先处理)
            If ngDict.exists(key) Then
                numbers = Split(ngDict(key), "+")
                For Each num In numbers
                    If IsNumeric(num) Then
                        colIndex = CInt(num) + 3
                        If colIndex >= 4 And colIndex <= 39 Then
                            With ws2.Cells(outputRow, colIndex)
                                .value = "NG"
                                .Interior.Color = RGB(255, 0, 0)
                            End With
                        End If
                    End If
                Next
            End If
            
            ' 标记OK穴号(绿色,排除已标记NG的)
            If okDict.exists(key) Then
                numbers = Split(okDict(key), "+")
                For Each num In numbers
                    If IsNumeric(num) Then
                        colIndex = CInt(num) + 3
                        If colIndex >= 4 And colIndex <= 39 Then
                            If ws2.Cells(outputRow, colIndex).value <> "NG" Then
                                With ws2.Cells(outputRow, colIndex)
                                    .value = "OK"
                                    .Interior.Color = RGB(0, 255, 0)
                                End With
                            End If
                        End If
                    End If
                Next
            End If
            
            outputRow = outputRow + 1
        Next
    End If
    
    Application.ScreenUpdating = True
    MsgBox "处理完成!共提取 " & dict.count & " 条记录", vbInformation
End Sub

Private Sub ProcessHoleNumbers(holeStr As String, ByRef dict As Object, key As String)
    If holeStr <> "" Then
        Dim numbers As Variant, num As Variant
        numbers = Split(holeStr, "+")
        
        For Each num In numbers
            If IsNumeric(num) Then
                If Not dict.exists(key) Then
                    dict.Add key, num
                ElseIf InStr(dict(key), num) = 0 Then
                    dict(key) = dict(key) & "+" & num
                End If
            End If
        Next
    End If
End Sub

3.镜片不良TOP


Sub CalculateLensDefects()
    Dim srcSheet As Worksheet, dstSheet As Worksheet
    Dim lastRow As Long, i As Long, col As Long
    Dim startDate As Date, endDate As Date
    Dim machineType As String
    Dim defectTitles(1 To 20) As String
    Dim defectSums(1 To 20) As Double
    
    ' 设置工作表对象
    Set srcSheet = Worksheets("镜片抽检履历")
    Set dstSheet = Worksheets("良率汇总")
    
    dstSheet.Range("Z19:AA38").ClearContents
    
    ' 复制缺陷类型标题到Z列(S3:AL3 → Z19:Z38)
    For col = 19 To 38
        defectTitles(col - 18) = srcSheet.Cells(3, col).value
        dstSheet.Cells(18 + (col - 18), "Z").value = defectTitles(col - 18)
    Next col
    
    ' 获取筛选条件
    startDate = dstSheet.Range("AA2").value
    endDate = dstSheet.Range("AA4").value
    machineType = Trim(dstSheet.Range("AA11").value)
    
    ' 初始化统计数组
    For i = 1 To 20
        defectSums(i) = 0
    Next i
    
    ' 计算有效数据行数
    lastRow = srcSheet.Cells(srcSheet.Rows.count, "B").End(xlUp).Row
    
    ' 核心统计逻辑
    For i = 4 To lastRow
        ' 日期范围筛选(B列)
        If srcSheet.Cells(i, "B").value >= startDate And _
           srcSheet.Cells(i, "B").value <= endDate Then
            
            ' 机种条件判断(H列)
            If machineType = "全部机种" Or srcSheet.Cells(i, "H").value = machineType Then
                ' 累加各缺陷类型数量(S:AL列)
                For col = 19 To 38
                    If IsNumeric(srcSheet.Cells(i, col).value) Then
                        defectSums(col - 18) = defectSums(col - 18) + srcSheet.Cells(i, col).value
                    End If
                Next col
            End If
        End If
    Next i
    
    ' 输出统计结果到AA列(S列和→AA19,T列和→AA20...)
    For i = 1 To 20
        dstSheet.Cells(18 + i, "AA").value = defectSums(i)
    Next i
    
    ' 按缺陷数量升序排序(Z19:AA38区域)
    With dstSheet.Range("Z19:AA38")
        .Sort Key1:=.Columns(2), Order1:=xlDescending, Header:=xlNo  'xlAscending
    End With
    
    MsgBox "镜片质量分析完成:" & vbCrLf & _
           "统计时段:" & startDate & " 至 " & endDate & vbCrLf & _
           IIf(machineType <> "", "指定机种:" & machineType, "全部机种"), _
           vbInformation, "操作完成"
End Sub

4.镜片公式计算


Option Explicit
Sub ProcessLensData()
    Dim wsLens As Worksheet, wsData As Worksheet
    Dim lastRow As Long, i As Long
    Dim missingList As String, errorLog As String
    Dim dict As Object, startDate As Date, endDate As Date
    
    Set dict = CreateObject("Scripting.Dictionary")
    Set wsLens = Sheets("镜片抽检履历")
    Set wsData = Sheets("单板数整理")
    
    ' 获取日期范围
    With wsLens
        startDate = .Range("M2").value
        endDate = .Range("Q2").value
    End With
    
    ' 构建机种件号字典
    With wsData
        For i = 2 To .Cells(.Rows.count, 1).End(xlUp).Row
            dict(.Cells(i, 1).value & "|" & .Cells(i, 2).value) = .Cells(i, 3).value
        Next
    End With
    
    ' 主处理流程
    With wsLens
        lastRow = .Cells(.Rows.count, 2).End(xlUp).Row
        For i = 4 To lastRow
            On Error Resume Next
            If IsDate(.Cells(i, 2).value) Then
                If .Cells(i, 2).value >= startDate And .Cells(i, 2).value <= endDate Then
                    ProcessLensRow .Rows(i), dict, missingList, errorLog
                End If
            End If
        Next
    End With
    
    ' 输出结果
    If Len(missingList) > 0 Then MsgBox "未匹配记录:" & vbCrLf & missingList
    If Len(errorLog) > 0 Then MsgBox "处理错误:" & errorLog
    MsgBox "镜片抽检数据处理完成!", vbInformation
End Sub

Private Sub ProcessLensRow(rng As Range, dict As Object, ByRef missList As String, ByRef errLog As String)
    Dim key As String, numCount As Integer
    On Error GoTo ErrorHandler
    
    ' 任务1:单板数匹配
    key = rng.Cells(1, 8).value & "|" & rng.Cells(1, 9).value
    If dict.exists(key) Then
        rng.Cells(1, 12).value = dict(key)
    Else
        rng.Cells(1, 12).value = "请录入该机种单板数"
        missList = missList & key & vbCrLf
    End If
    
    ' 任务2:抽检数计算
    numCount = CountNumbers(rng.Cells(1, 10).value) + CountNumbers(rng.Cells(1, 11).value)
    rng.Cells(1, 13).value = rng.Cells(1, 12).value * IIf(numCount >= 3, numCount, 3)
    
    ' 任务3-5处理
    With rng
        .Cells(1, 17).value = Application.Sum(.Range("S1:AL1"))
        If .Cells(1, 13).value <> 0 Then
            .Cells(1, 18).value = .Cells(1, 17).value / .Cells(1, 13).value
            .Cells(1, 18).NumberFormat = "0.0%"
        End If
        
        .Cells(1, 16).value = IIf(.Cells(1, 18).value > 0.02 Or _
            AnyPositive(.Range("Y1,AB1,AJ1,AL1,AH1,AI1,AK1")), "退", "入")
    End With
    Exit Sub
    
ErrorHandler:
    errLog = errLog & "行" & rng.Row & "列" & Split(Err.Source, "$")(1) & "; "
End Sub

5.镜片良率计算


Option Explicit

Sub CalculateYieldAndAverage()
    Dim wsSource As Worksheet, wsTarget As Worksheet
    Dim lastRow As Long, i As Long, j As Long, k As Long
    Dim dictMachine As Object, arrMachines(), arrDates()
    Dim arrResults(), totalCount As Long, rejectCount As Long
    Dim targetDate As Date, currentMachine As String
    Dim sumValues As Double, countValues As Long
    
    ' 设置工作表对象
    Set wsSource = Worksheets("镜片抽检履历")
    Set wsTarget = Worksheets("镜片机种良率")
    Set dictMachine = CreateObject("Scripting.Dictionary")
    
    ' 清除目标区域
    wsTarget.Range("A3:AG1000").ClearContents
    
    ' 获取机种不重复值(H列)
    lastRow = wsSource.Cells(wsSource.Rows.count, "H").End(xlUp).Row
    For i = 4 To lastRow
        currentMachine = Trim(wsSource.Cells(i, "H").value)
        If currentMachine <> "" And Not dictMachine.exists(currentMachine) Then
            dictMachine.Add currentMachine, 1
        End If
    Next i
    
    ' 排序并输出机种到A列
    arrMachines = dictMachine.keys
    Call BubbleSort(arrMachines)
    wsTarget.Range("A3").Resize(UBound(arrMachines) + 1).value = Application.Transpose(arrMachines)
    
    ' 获取日期范围(C2:AG2)
    arrDates = wsTarget.Range("C2:AG2").value
    
    ' 初始化结果数组
    ReDim arrResults(1 To UBound(arrMachines) + 1, 1 To UBound(arrDates, 2))
    
    ' 计算良率矩阵
    For i = 1 To UBound(arrMachines) + 1
        For j = 1 To UBound(arrDates, 2)
            targetDate = arrDates(1, j)
            totalCount = 0
            rejectCount = 0
            
            ' 统计符合条件的数据
            For k = 4 To lastRow
                If wsSource.Cells(k, "H").value = arrMachines(i - 1) And _
                   wsSource.Cells(k, "B").value = targetDate Then
                    totalCount = totalCount + 1
                    If wsSource.Cells(k, "P").value = "退" Then
                        rejectCount = rejectCount + 1
                    End If
                End If
            Next k
            
            ' 计算良率百分比
            If totalCount > 0 Then
                arrResults(i, j) = Round((totalCount - rejectCount) / totalCount, 4)
            End If
        Next j
    Next i
    
    ' 输出结果并设置格式
    With wsTarget.Range("C3").Resize(UBound(arrResults, 1), UBound(arrResults, 2))
        .value = arrResults
        .NumberFormat = "0.00%"
    End With
    
    ' 计算行平均值
    For i = 1 To UBound(arrMachines) + 1
        sumValues = 0
        countValues = 0
        For j = 1 To UBound(arrDates, 2)
            If Not IsEmpty(arrResults(i, j)) Then
                sumValues = sumValues + arrResults(i, j)
                countValues = countValues + 1
            End If
        Next j
        
        If countValues > 0 Then
            wsTarget.Cells(2 + i, "B").value = Round(sumValues / countValues, 4)
        End If
    Next i
    
    ' 设置平均值列格式
    wsTarget.Range("B3:B1000").NumberFormat = "0.00%"
    
    MsgBox "计算完成:" & vbCrLf & _
           "处理机种数量:" & UBound(arrMachines) + 1 & vbCrLf & _
           "处理日期数量:" & UBound(arrDates, 2), vbInformation
End Sub

' 冒泡排序算法
Sub BubbleSort(arr)
    Dim i As Long, j As Long
    Dim temp As Variant
    For i = LBound(arr) To UBound(arr) - 1
        For j = i + 1 To UBound(arr)
            If arr(i) > arr(j) Then
                temp = arr(i)
                arr(i) = arr(j)
                arr(j) = temp
            End If
        Next j
    Next i
End Sub

6.镜片批退率


Sub CalculateYieldRate()
    Dim wsData As Worksheet, wsReport As Worksheet
    Dim startDate As Date, endDate As Date
    Dim lastRow As Long, dict As Object
    Dim arrData(), arrResult(), outputRow As Long
    Dim i As Long, key As Variant, isSingleDate As Boolean
    
    ' 初始化设置
    On Error GoTo ErrorHandler
    Application.ScreenUpdating = False
    Set wsData = Worksheets("镜片抽检履历")
    Set wsReport = Worksheets("良率汇总")
    Set dict = CreateObject("Scripting.Dictionary")
    
    ' 清除旧数据
    wsReport.Range("AC4:AF" & wsReport.Rows.count).ClearContents
    
    ' 日期验证处理
    If IsEmpty(wsReport.Range("AA2")) Or IsEmpty(wsReport.Range("AA4")) Then
        MsgBox "请在AA2和AA4单元格输入有效日期", vbCritical
        Exit Sub
    End If
    
    On Error Resume Next
    startDate = CDate(wsReport.Range("AA2").value)
    endDate = CDate(wsReport.Range("AA4").value)
    If Err.Number <> 0 Then
        MsgBox "日期格式不正确,请检查AA2和AA4单元格", vbCritical
        Exit Sub
    End If
    On Error GoTo ErrorHandler
    
    ' 判断是单日期还是日期范围
    isSingleDate = (DateDiff("d", startDate, endDate) = 0)
    
    ' 数据加载
    lastRow = wsData.Cells(wsData.Rows.count, "B").End(xlUp).Row
    If lastRow < 4 Then
        MsgBox "抽检履历表无有效数据", vbExclamation
        Exit Sub
    End If
    arrData = wsData.Range("B4:R" & lastRow).value
    
    ' 核心统计逻辑
    For i = LBound(arrData) To UBound(arrData)
        If IsDate(arrData(i, 1)) Then
            Dim currentDate As Date
            currentDate = CDate(arrData(i, 1))
            
            ' 检查日期是否符合条件
            If (isSingleDate And DateValue(currentDate) = DateValue(startDate)) Or _
               (Not isSingleDate And currentDate >= startDate And currentDate <= endDate) Then
                
                Dim model As String
                model = Trim(CStr(arrData(i, 7)))
                
                ' 跳过空机种
                If model = "" Then GoTo NextItem
                
                ' 初始化字典项
                If Not dict.exists(model) Then
                    dict.Add model, Array(0, 0) ' (总批次, 退批次)
                End If
                
                ' 统计总数和退料数(不使用total = dict(key)(0)方式)
                dict(model)(0) = dict(model)(0) + 1
                If Trim(arrData(i, 15)) = "退" Then
                    dict(model)(1) = dict(model)(1) + 1
                End If
            End If
        End If
NextItem:
    Next i
    
    ' 结果输出
    If dict.count > 0 Then
        ReDim arrResult(1 To dict.count, 1 To 4)
        outputRow = 1
        
        ' 使用字典键进行计数统计
        For Each key In dict.keys
            Dim total As Long, reject As Long
            total = 0
            reject = 0
            
            ' 重新计数(不使用dict(key)(0)方式)
            For i = LBound(arrData) To UBound(arrData)
                If IsDate(arrData(i, 1)) Then
                    currentDate = CDate(arrData(i, 1))
                    If (isSingleDate And DateValue(currentDate) = DateValue(startDate)) Or _
                       (Not isSingleDate And currentDate >= startDate And currentDate <= endDate) Then
                        If Trim(CStr(arrData(i, 7))) = key Then
                            total = total + 1
                            If Trim(arrData(i, 15)) = "退" Then
                                reject = reject + 1
                            End If
                        End If
                    End If
                End If
            Next i
            
            arrResult(outputRow, 1) = key
            arrResult(outputRow, 2) = total
            arrResult(outputRow, 3) = reject
            If total > 0 Then
                arrResult(outputRow, 4) = reject / total
            Else
                arrResult(outputRow, 4) = 0
            End If
            outputRow = outputRow + 1
        Next key
        
        With wsReport
            .Range("AC4").Resize(dict.count, 4) = arrResult
            .Range("AF4:AF" & 3 + dict.count).NumberFormat = "0.00%"
            
            ' 按批退率升序排序
            If dict.count > 1 Then
                .Range("AC4:AF" & 3 + dict.count).Sort _
                    Key1:=.Range("AF4"), Order1:=xlDescending, _
                    Header:=xlNo
            End If
        End With
    End If
    
    Application.ScreenUpdating = True
    MsgBox "处理完成!共统计 " & dict.count & " 个机种", vbInformation
    Exit Sub
    
ErrorHandler:
    Application.ScreenUpdating = True
    MsgBox "错误 " & Err.Number & ": " & Err.Description, vbCritical
End Sub

7.镜筒不良TOP


Sub CalculateLensDefects()
    Dim srcSheet As Worksheet, dstSheet As Worksheet
    Dim lastRow As Long, i As Long, col As Long
    Dim startDate As Date, endDate As Date
    Dim machineType As String
    Dim defectTitles(1 To 12) As String
    Dim defectSums(1 To 12) As Double
    
    ' 设置工作表对象
    Set srcSheet = Worksheets("镜筒抽检履历")
    Set dstSheet = Worksheets("良率汇总")
    
    dstSheet.Range("AH19:AI30").ClearContents
    
    ' 复制缺陷类型标题到AH列(R3:AC3 → AH19:AH30)
    For col = 18 To 29
        defectTitles(col - 17) = srcSheet.Cells(3, col).value
        dstSheet.Cells(18 + (col - 17), "AH").value = defectTitles(col - 17)
    Next col
    
    ' 获取筛选条件
    startDate = dstSheet.Range("AI2").value
    endDate = dstSheet.Range("AI4").value
    machineType = Trim(dstSheet.Range("AI11").value)
    
    ' 初始化统计数组
    For i = 1 To 12
        defectSums(i) = 0
    Next i
    
    ' 计算有效数据行数
    lastRow = srcSheet.Cells(srcSheet.Rows.count, "B").End(xlUp).Row
    
    ' 核心统计逻辑
    For i = 4 To lastRow
        ' 日期范围筛选(B列)
        If srcSheet.Cells(i, "B").value >= startDate And _
           srcSheet.Cells(i, "B").value <= endDate Then
            
            ' 机种条件判断(G列)
            If machineType = "全部机种" Or srcSheet.Cells(i, "G").value = machineType Then
                ' 累加各缺陷类型数量(R:AC列)
                For col = 18 To 29
                    If IsNumeric(srcSheet.Cells(i, col).value) Then
                        defectSums(col - 17) = defectSums(col - 17) + srcSheet.Cells(i, col).value
                    End If
                Next col
            End If
        End If
    Next i
    
    ' 输出统计结果到AI列(R列和→AI19,S列和→AI20...)
    For i = 1 To 12
        dstSheet.Cells(18 + i, "AI").value = defectSums(i)
    Next i
    
    ' 按缺陷数量升序排序(AH19:AI30区域)
    With dstSheet.Range("AH19:AI30")
        .Sort Key1:=.Columns(2), Order1:=xlDescending, Header:=xlNo
    End With
    
    MsgBox "镜筒质量分析完成:" & vbCrLf & _
           "统计时段:" & startDate & " 至 " & endDate & vbCrLf & _
           IIf(machineType <> "", "指定机种:" & machineType, "全部机种"), _
           vbInformation, "操作完成"
End Sub

8.镜筒公式计算

Option Explicit
Sub ProcessBarrelData()
    Dim wsBarrel As Worksheet, wsData As Worksheet
    Dim lastRow As Long, i As Long
    Dim missingList As String, errorLog As String
    Dim dict As Object, startDate As Date, endDate As Date
    
    Set dict = CreateObject("Scripting.Dictionary")
    Set wsBarrel = Sheets("镜筒抽检履历")
    Set wsData = Sheets("单板数整理")
    
    ' 获取日期范围
    With wsBarrel
        startDate = .Range("L2").value
        endDate = .Range("P2").value
    End With
    
    ' 构建机种件号字典
    With wsData
        For i = 2 To .Cells(.Rows.count, 1).End(xlUp).Row
            dict(.Cells(i, 1).value & "|" & .Cells(i, 2).value) = .Cells(i, 3).value
        Next
    End With
    
    ' 主处理流程
    With wsBarrel
        lastRow = .Cells(.Rows.count, 2).End(xlUp).Row
        For i = 4 To lastRow
            On Error Resume Next
            If IsDate(.Cells(i, 2).value) Then
                If .Cells(i, 2).value >= startDate And .Cells(i, 2).value <= endDate Then
                    ProcessBarrelRow .Rows(i), dict, missingList, errorLog
                End If
            End If
        Next
    End With
    
    ' 输出结果
    If Len(missingList) > 0 Then MsgBox "未匹配记录:" & vbCrLf & missingList
    If Len(errorLog) > 0 Then MsgBox "处理错误:" & errorLog
    MsgBox "镜片抽检数据处理完成!", vbInformation
End Sub

Private Sub ProcessBarrelRow(rng As Range, dict As Object, ByRef missList As String, ByRef errLog As String)
    Dim key As String, numCount As Integer
    On Error GoTo ErrorHandler
    
    ' 任务6:单板数匹配
    key = rng.Cells(1, 7).value & "|" & rng.Cells(1, 8).value
    If dict.exists(key) Then
        rng.Cells(1, 11).value = dict(key)
    Else
        rng.Cells(1, 11).value = "请录入该机种单板数"
        missList = missList & key & vbCrLf
    End If
    
    ' 任务7:抽检数计算
    numCount = CountNumbers(rng.Cells(1, 9).value) + CountNumbers(rng.Cells(1, 10).value)
    rng.Cells(1, 12).value = rng.Cells(1, 11).value * IIf(numCount >= 3, numCount, 3)
    
    ' 任务8-10处理
    With rng
        .Cells(1, 16).value = Application.Sum(.Range("R1:AC1"))
        If .Cells(1, 12).value <> 0 Then
            .Cells(1, 17).value = .Cells(1, 16).value / .Cells(1, 12).value
            .Cells(1, 17).NumberFormat = "0.0%"
        End If
        
        .Cells(1, 15).value = IIf(.Cells(1, 17).value > 0.02 Or _
            .Cells(1, 28).value > 0, "退", "入")
    End With
    Exit Sub
    
ErrorHandler:
    errLog = errLog & "行" & rng.Row & "列" & Split(Err.Source, "$")(1) & "; "
End Sub

9.镜筒良率计算


Sub CalculateYieldAndAverage()
    Dim wsSource As Worksheet, wsTarget As Worksheet
    Dim lastRow As Long, i As Long, j As Long, k As Long
    Dim dictMachine As Object, arrMachines(), arrDates()
    Dim arrResults(), totalCount As Long, rejectCount As Long
    Dim targetDate As Date, currentMachine As String
    Dim sumValues As Double, countValues As Long
    
    ' 设置工作表对象
    Set wsSource = Worksheets("镜筒抽检履历")
    Set wsTarget = Worksheets("镜筒机种良率")
    Set dictMachine = CreateObject("Scripting.Dictionary")
    
    ' 清除目标区域
    wsTarget.Range("A3:AG1000").ClearContents
    
    ' 获取机种不重复值(G列)
    lastRow = wsSource.Cells(wsSource.Rows.count, "G").End(xlUp).Row
    For i = 4 To lastRow
        currentMachine = Trim(wsSource.Cells(i, "G").value)
        If currentMachine <> "" And Not dictMachine.exists(currentMachine) Then
            dictMachine.Add currentMachine, 1
        End If
    Next i
    
    ' 排序并输出机种到A列
    arrMachines = dictMachine.keys
    Call BubbleSort(arrMachines)
    wsTarget.Range("A3").Resize(UBound(arrMachines) + 1).value = Application.Transpose(arrMachines)
    
    ' 获取日期范围(C2:AG2)
    arrDates = wsTarget.Range("C2:AG2").value
    
    ' 初始化结果数组
    ReDim arrResults(1 To UBound(arrMachines) + 1, 1 To UBound(arrDates, 2))
    
    ' 计算良率矩阵
    For i = 1 To UBound(arrMachines) + 1
        For j = 1 To UBound(arrDates, 2)
            targetDate = arrDates(1, j)
            totalCount = 0
            rejectCount = 0
            
            ' 统计符合条件的数据
            For k = 4 To lastRow
                If wsSource.Cells(k, "G").value = arrMachines(i - 1) And _
                   wsSource.Cells(k, "B").value = targetDate Then
                    totalCount = totalCount + 1
                    If wsSource.Cells(k, "O").value = "退" Then
                        rejectCount = rejectCount + 1
                    End If
                End If
            Next k
            
            ' 计算良率百分比
            If totalCount > 0 Then
                arrResults(i, j) = Round((totalCount - rejectCount) / totalCount, 4)
            End If
        Next j
    Next i
    
    ' 输出结果并设置格式
    With wsTarget.Range("C3").Resize(UBound(arrResults, 1), UBound(arrResults, 2))
        .value = arrResults
        .NumberFormat = "0.00%"
    End With
    
    ' 计算行平均值
    For i = 1 To UBound(arrMachines) + 1
        sumValues = 0
        countValues = 0
        For j = 1 To UBound(arrDates, 2)
            If Not IsEmpty(arrResults(i, j)) Then
                sumValues = sumValues + arrResults(i, j)
                countValues = countValues + 1
            End If
        Next j
        
        If countValues > 0 Then
            wsTarget.Cells(2 + i, "B").value = Round(sumValues / countValues, 4)
        End If
    Next i
    
    ' 设置平均值列格式
    wsTarget.Range("B3:B1000").NumberFormat = "0.00%"
    
    MsgBox "计算完成:" & vbCrLf & _
           "处理机种数量:" & UBound(arrMachines) + 1 & vbCrLf & _
           "处理日期数量:" & UBound(arrDates, 2), vbInformation
End Sub

' 冒泡排序算法
Sub BubbleSort(arr)
    Dim i As Long, j As Long
    Dim temp As Variant
    For i = LBound(arr) To UBound(arr) - 1
        For j = i + 1 To UBound(arr)
            If arr(i) > arr(j) Then
                temp = arr(i)
                arr(i) = arr(j)
                arr(j) = temp
            End If
        Next j
    Next i
End Sub

10.镜筒批退率


Sub CalculateYieldRate()
    Dim wsData As Worksheet, wsReport As Worksheet
    Dim startDate As Date, endDate As Date
    Dim lastRow As Long, dict As Object
    Dim arrData(), arrResult(), outputRow As Long
    Dim i As Long, key As Variant, isSingleDate As Boolean
    
    ' 初始化设置
    On Error GoTo ErrorHandler
    Application.ScreenUpdating = False
    Set wsData = Worksheets("镜筒抽检履历")
    Set wsReport = Worksheets("良率汇总")
    Set dict = CreateObject("Scripting.Dictionary")
    
    ' 清除旧数据
    wsReport.Range("AK4:AN" & wsReport.Rows.count).ClearContents
    
    ' 日期验证处理
    If IsEmpty(wsReport.Range("AI2")) Or IsEmpty(wsReport.Range("AI4")) Then
        MsgBox "请在AI2和AI4单元格输入有效日期", vbCritical
        Exit Sub
    End If
    
    On Error Resume Next
    startDate = CDate(wsReport.Range("AI2").value)
    endDate = CDate(wsReport.Range("AI4").value)
    If Err.Number <> 0 Then
        MsgBox "日期格式不正确,请检查AI2和AI4单元格", vbCritical
        Exit Sub
    End If
    On Error GoTo ErrorHandler
    
    ' 判断是单日期还是日期范围
    isSingleDate = (DateDiff("d", startDate, endDate) = 0)
    
    ' 数据加载
    lastRow = wsData.Cells(wsData.Rows.count, "B").End(xlUp).Row
    If lastRow < 4 Then
        MsgBox "抽检履历表无有效数据", vbExclamation
        Exit Sub
    End If
    arrData = wsData.Range("B4:O" & lastRow).value
    
    ' 核心统计逻辑
    For i = LBound(arrData) To UBound(arrData)
        If IsDate(arrData(i, 1)) Then
            Dim currentDate As Date
            currentDate = CDate(arrData(i, 1))
            
            ' 检查日期是否符合条件
            If (isSingleDate And DateValue(currentDate) = DateValue(startDate)) Or _
               (Not isSingleDate And currentDate >= startDate And currentDate <= endDate) Then
                
                Dim model As String
                model = Trim(CStr(arrData(i, 6)))
                
                ' 跳过空机种
                If model = "" Then GoTo NextItem
                
                ' 初始化字典项
                If Not dict.exists(model) Then
                    dict.Add model, Array(0, 0) ' (总批次, 退批次)
                End If
                
                ' 统计总数和退料数(不使用total = dict(key)(0)方式)
                dict(model)(0) = dict(model)(0) + 1
                If Trim(arrData(i, 14)) = "退" Then
                    dict(model)(1) = dict(model)(1) + 1
                End If
            End If
        End If
NextItem:
    Next i
    
    ' 结果输出
    If dict.count > 0 Then
        ReDim arrResult(1 To dict.count, 1 To 4)
        outputRow = 1
        
        ' 使用字典键进行计数统计
        For Each key In dict.keys
            Dim total As Long, reject As Long
            total = 0
            reject = 0
            
            ' 重新计数(不使用dict(key)(0)方式)
            For i = LBound(arrData) To UBound(arrData)
                If IsDate(arrData(i, 1)) Then
                    currentDate = CDate(arrData(i, 1))
                    If (isSingleDate And DateValue(currentDate) = DateValue(startDate)) Or _
                       (Not isSingleDate And currentDate >= startDate And currentDate <= endDate) Then
                        If Trim(CStr(arrData(i, 6))) = key Then
                            total = total + 1
                            If Trim(arrData(i, 14)) = "退" Then
                                reject = reject + 1
                            End If
                        End If
                    End If
                End If
            Next i
            
            arrResult(outputRow, 1) = key
            arrResult(outputRow, 2) = total
            arrResult(outputRow, 3) = reject
            If total > 0 Then
                arrResult(outputRow, 4) = reject / total
            Else
                arrResult(outputRow, 4) = 0
            End If
            outputRow = outputRow + 1
        Next key
        
        With wsReport
            .Range("AK4").Resize(dict.count, 4) = arrResult
            .Range("AN4:AN" & 3 + dict.count).NumberFormat = "0.00%"
            
            ' 按批退率升序排序
            If dict.count > 1 Then
                .Range("AK4:AN" & 3 + dict.count).Sort _
                    Key1:=.Range("AN4"), Order1:=xlDescending, _
                    Header:=xlNo
            End If
        End With
    End If
    
    Application.ScreenUpdating = True
    MsgBox "处理完成!共统计 " & dict.count & " 个机种", vbInformation
    Exit Sub
    
ErrorHandler:
    Application.ScreenUpdating = True
    MsgBox "错误 " & Err.Number & ": " & Err.Description, vbCritical
End Sub

二、反射率报表

1.机台通过率


Option Explicit

Sub AnalyzeMachinePassRate()
    Dim ws1 As Worksheet, ws2 As Worksheet
    Dim lastRow1 As Long, lastRow2 As Long
    Dim startDate As Date, endDate As Date
    Dim dict As Object, key As String
    Dim i As Long, j As Long, k As Long
    Dim dateCol As Long
    Dim a As Long, b As Long, c As Long, d As Long
    Dim isLens As Boolean
    
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    
    Set ws1 = Worksheets("测试记录")
    Set ws2 = Worksheets("机台分析")
    Set dict = CreateObject("Scripting.Dictionary")
    
    ' 清除旧数据
    ws2.Range("A3:AI1000").ClearContents
    
    ' 获取日期范围
    startDate = ws2.Range("L1").Value
    endDate = ws2.Range("P1").Value
    
    ' 判断分析模式
    isLens = (ws2.Range("T1").Value = "镜片")
    
    ' 步骤1:提取不重复的机台
    lastRow1 = ws1.Cells(ws1.Rows.count, "A").End(xlUp).Row
    k = 3 ' 从第3行开始写入
    
    For i = 3 To lastRow1
        If ws1.Cells(i, 1).Value >= startDate And ws1.Cells(i, 1).Value <= endDate Then
            ' 根据模式判断件号条件
            If (isLens And ws1.Cells(i, 8).Value > 800) Or _
               (Not isLens And ws1.Cells(i, 8).Value < 800) Then
                key = ws1.Cells(i, 5).Value ' 机台
                If Not dict.exists(key) Then
                    dict.Add key, k
                    ws2.Cells(k, 3).Value = key ' 机台
                    k = k + 1
                End If
            End If
        End If
    Next i
    
    ' 步骤2-9:计算各项指标
    lastRow2 = ws2.Cells(ws2.Rows.count, "C").End(xlUp).Row
    
    For i = 3 To lastRow2
        ' 初始化合计数据
        c = 0
        d = 0
        
        ' 遍历日期列
        For dateCol = 5 To 35 ' E到AI列
            If ws2.Cells(2, dateCol).Value >= startDate And ws2.Cells(2, dateCol).Value <= endDate Then
                ' 初始化每日数据
                a = 0
                b = 0
                
                ' 遍历测试记录
                For j = 3 To lastRow1
                    If ws1.Cells(j, 1).Value = ws2.Cells(2, dateCol).Value Then
                        If ws1.Cells(j, 5).Value = ws2.Cells(i, 3).Value Then
                            ' 步骤2/7:总测试数
                            a = a + 1
                            c = c + 1
                            
                            ' 步骤5/8:NG数
                            If ws1.Cells(j, 11).Value = "NG" Then
                                b = b + 1
                                d = d + 1
                            End If
                        End If
                    End If
                Next j
                
                ' 步骤6:计算每日通过率
                If a > 0 Then
                    ws2.Cells(i, dateCol).Value = Round((a - b) / a, 3)
                    ws2.Cells(i, dateCol).NumberFormat = "0.0%"
                End If
            End If
        Next dateCol
        
        ' 步骤9:计算合计通过率
        If c > 0 Then
            ws2.Cells(i, 4).Value = Round((c - d) / c, 3)
            ws2.Cells(i, 4).NumberFormat = "0.0%"
        End If
    Next i
    
    ' 步骤10:按通过率升序排序
    With ws2.Sort
        .SortFields.Clear
        .SortFields.Add key:=Range("D3:D" & lastRow2), SortOn:=xlSortOnValues, Order:=xlAscending
        .SetRange Range("C3:AI" & lastRow2)
        .Header = xlNo
        .Apply
    End With
    
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
    
    MsgBox "机台通过率分析完成!当前模式:" & ws2.Range("T1").Value, vbInformation
End Sub

2.镜片通过率圈数分析


Option Explicit

Sub AnalyzeLensPassRate()
    Dim ws1 As Worksheet, ws2 As Worksheet
    Dim lastRow1 As Long, lastRow2 As Long
    Dim startDate As Date, endDate As Date
    Dim dict As Object, key As String
    Dim i As Long, j As Long, k As Long
    Dim dateCol As Long
    Dim a As Long, b As Long, c As Long, d As Long
    Dim posCount As Long
    
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    
    Set ws1 = Worksheets("测试记录")
    Set ws2 = Worksheets("镜片通过率圈数分析")
    Set dict = CreateObject("Scripting.Dictionary")
    
    ' 步骤0:清除旧数据
    ws2.Range("A3:AL1000").ClearContents
    
    ' 获取日期范围
    startDate = ws2.Range("L1").Value
    endDate = ws2.Range("P1").Value
    
    ' 步骤1:提取不重复的机种和件号组合
    lastRow1 = ws1.Cells(ws1.Rows.count, "A").End(xlUp).Row
    k = 3 ' 从第3行开始写入
    
    For i = 3 To lastRow1
        If ws1.Cells(i, 1).Value >= startDate And ws1.Cells(i, 1).Value <= endDate Then
            If ws1.Cells(i, 8).Value > 800 Then
                key = ws1.Cells(i, 7).Value & "|" & ws1.Cells(i, 8).Value
                If Not dict.exists(key) Then
                    dict.Add key, k
                    ws2.Cells(k, 2).Value = ws1.Cells(i, 7).Value ' 机种
                    ws2.Cells(k, 3).Value = ws1.Cells(i, 8).Value ' 件号
                    k = k + 1
                End If
            End If
        End If
    Next i
    
    ' 步骤2:填充客户工艺
    lastRow2 = ws2.Cells(ws2.Rows.count, "B").End(xlUp).Row
    For i = 3 To lastRow2
        For j = 3 To lastRow1
            If ws1.Cells(j, 1).Value >= startDate And ws1.Cells(j, 1).Value <= endDate Then
                If ws1.Cells(j, 7).Value = ws2.Cells(i, 2).Value And _
                   ws1.Cells(j, 8).Value = ws2.Cells(i, 3).Value Then
                    ws2.Cells(i, 1).Value = ws1.Cells(j, 18).Value ' 客户工艺
                    Exit For
                End If
            End If
        Next j
    Next i
    
    ' 步骤3:排序
    With ws2.Sort
        .SortFields.Clear
        .SortFields.Add key:=Range("A3:A" & lastRow2), SortOn:=xlSortOnValues, Order:=xlAscending
        .SortFields.Add key:=Range("B3:B" & lastRow2), SortOn:=xlSortOnValues, Order:=xlAscending
        .SetRange Range("A3:AP" & lastRow2)
        .Header = xlNo
        .Apply
    End With
    
    ' 步骤4-12:计算各项指标
    For i = 3 To lastRow2
        ' 初始化合计数据
        c = 0
        d = 0
        
        ' 遍历日期列
        For dateCol = 5 To 35 ' E到AI列
            If ws2.Cells(2, dateCol).Value >= startDate And ws2.Cells(2, dateCol).Value <= endDate Then
                ' 初始化每日数据
                a = 0
                b = 0
                
                ' 遍历测试记录
                For j = 3 To lastRow1
                    If ws1.Cells(j, 1).Value = ws2.Cells(2, dateCol).Value Then
                        If ws1.Cells(j, 7).Value = ws2.Cells(i, 2).Value And _
                           ws1.Cells(j, 8).Value = ws2.Cells(i, 3).Value Then
                            ' 步骤4/7:总测试数(整罩计3)
                            a = a + 3
                            c = c + 3
                            
                            ' 步骤5/8:NG数(按位置计数)
                            If ws1.Cells(j, 11).Value = "NG" Then
                                posCount = 0
                                If InStr(ws1.Cells(j, 14).Value, "上") > 0 Then posCount = posCount + 1
                                If InStr(ws1.Cells(j, 14).Value, "中") > 0 Then posCount = posCount + 1
                                If InStr(ws1.Cells(j, 14).Value, "下") > 0 Then posCount = posCount + 1
                                If InStr(ws1.Cells(j, 14).Value, "整罩") > 0 Then posCount = posCount + 3
                                
                                b = b + posCount
                                d = d + posCount
                                
                                ' 步骤10-12:特定异常项目计数(含位置计数)
                                If InStr(ws1.Cells(j, 12).Value, "LAB") > 0 Then
                                    ws2.Cells(i, 36).Value = ws2.Cells(i, 36).Value + posCount ' AJ列
                                End If
                                If InStr(ws1.Cells(j, 12).Value, "膜色") > 0 Then
                                    ws2.Cells(i, 37).Value = ws2.Cells(i, 37).Value + posCount ' AK列
                                End If
                                If InStr(ws1.Cells(j, 12).Value, "反射率") > 0 Then
                                    ws2.Cells(i, 38).Value = ws2.Cells(i, 38).Value + posCount ' AL列
                                End If
                            End If
                        End If
                    End If
                Next j
                
                ' 步骤6:计算每日通过率
                If a > 0 Then
                    ws2.Cells(i, dateCol).Value = Round((a - b) / a, 3)
                    ws2.Cells(i, dateCol).NumberFormat = "0.0%"
                End If
            End If
        Next dateCol
        
        ' 步骤9:计算合计通过率
        If c > 0 Then
            ws2.Cells(i, 4).Value = Round((c - d) / c, 3)
            ws2.Cells(i, 4).NumberFormat = "0.0%"
        End If
    Next i
    
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
    
    MsgBox "镜片通过率圈数分析完成!", vbInformation
End Sub

3.镜片通过率罩次分析


Option Explicit

Sub AnalyzeLensPassRate()
    Dim ws1 As Worksheet, ws2 As Worksheet
    Dim lastRow1 As Long, lastRow2 As Long
    Dim startDate As Date, endDate As Date
    Dim dict As Object, key As String
    Dim i As Long, j As Long, k As Long
    Dim dateCol As Long
    Dim a As Long, b As Long, c As Long, d As Long
    Dim upCount As Long, midCount As Long, downCount As Long, fullCount As Long
    
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    
    Set ws1 = Worksheets("测试记录")
    Set ws2 = Worksheets("镜片通过率罩次分析")
    Set dict = CreateObject("Scripting.Dictionary")
    
    ' 清除旧数据
    ws2.Range("A3:AP1000").ClearContents
    
    ' 获取日期范围
    startDate = ws2.Range("L1").Value
    endDate = ws2.Range("P1").Value
    
    ' 步骤1:提取不重复的机种和件号组合
    lastRow1 = ws1.Cells(ws1.Rows.count, "A").End(xlUp).Row
    k = 3 ' 从第3行开始写入
    
    For i = 3 To lastRow1
        If ws1.Cells(i, 1).Value >= startDate And ws1.Cells(i, 1).Value <= endDate Then
            If ws1.Cells(i, 8).Value > 800 Then
                key = ws1.Cells(i, 7).Value & "|" & ws1.Cells(i, 8).Value
                If Not dict.exists(key) Then
                    dict.Add key, k
                    ws2.Cells(k, 2).Value = ws1.Cells(i, 7).Value ' 机种
                    ws2.Cells(k, 3).Value = ws1.Cells(i, 8).Value ' 件号
                    k = k + 1
                End If
            End If
        End If
    Next i
    
    ' 步骤2:填充客户工艺
    lastRow2 = ws2.Cells(ws2.Rows.count, "B").End(xlUp).Row
    For i = 3 To lastRow2
        For j = 3 To lastRow1
            If ws1.Cells(j, 1).Value >= startDate And ws1.Cells(j, 1).Value <= endDate Then
                If ws1.Cells(j, 7).Value = ws2.Cells(i, 2).Value And _
                   ws1.Cells(j, 8).Value = ws2.Cells(i, 3).Value Then
                    ws2.Cells(i, 1).Value = ws1.Cells(j, 18).Value ' 客户工艺
                    Exit For
                End If
            End If
        Next j
    Next i
    
    ' 步骤3:排序
    With ws2.Sort
        .SortFields.Clear
        .SortFields.Add key:=Range("A3:A" & lastRow2), SortOn:=xlSortOnValues, Order:=xlAscending
        .SortFields.Add key:=Range("B3:B" & lastRow2), SortOn:=xlSortOnValues, Order:=xlAscending
        .SetRange Range("A3:AP" & lastRow2)
        .Header = xlNo
        .Apply
    End With
    
    ' 步骤4-16:计算各项指标
    For i = 3 To lastRow2
        ' 初始化合计数据
        c = 0
        d = 0
        upCount = 0
        midCount = 0
        downCount = 0
        fullCount = 0
        
        ' 遍历日期列
        For dateCol = 5 To 35 ' E到AI列
            If ws2.Cells(2, dateCol).Value >= startDate And ws2.Cells(2, dateCol).Value <= endDate Then
                ' 初始化每日数据
                a = 0
                b = 0
                
                ' 遍历测试记录
                For j = 3 To lastRow1
                    If ws1.Cells(j, 1).Value = ws2.Cells(2, dateCol).Value Then
                        If ws1.Cells(j, 7).Value = ws2.Cells(i, 2).Value And _
                           ws1.Cells(j, 8).Value = ws2.Cells(i, 3).Value Then
                            ' 步骤4/7:总测试数
                            a = a + 1
                            c = c + 1
                            
                            ' 步骤5/8:NG数
                            If ws1.Cells(j, 11).Value = "NG" Then
                                b = b + 1
                                d = d + 1
                                
                                ' 步骤10-12:特定异常项目计数
                                If InStr(ws1.Cells(j, 12).Value, "LAB") > 0 Then
                                    ws2.Cells(i, 36).Value = ws2.Cells(i, 36).Value + 1 ' AJ列
                                End If
                                If InStr(ws1.Cells(j, 12).Value, "膜色") > 0 Then
                                    ws2.Cells(i, 37).Value = ws2.Cells(i, 37).Value + 1 ' AK列
                                End If
                                If InStr(ws1.Cells(j, 12).Value, "反射率") > 0 Then
                                    ws2.Cells(i, 38).Value = ws2.Cells(i, 38).Value + 1 ' AL列
                                End If
                                
                                ' 步骤13-16:位置统计
                                If InStr(ws1.Cells(j, 14).Value, "上") > 0 Then upCount = upCount + 1
                                If InStr(ws1.Cells(j, 14).Value, "中") > 0 Then midCount = midCount + 1
                                If InStr(ws1.Cells(j, 14).Value, "下") > 0 Then downCount = downCount + 1
                                If InStr(ws1.Cells(j, 14).Value, "整罩") > 0 Then fullCount = fullCount + 1
                            End If
                        End If
                    End If
                Next j
                
                ' 步骤6:计算每日通过率
                If a > 0 Then
                    ws2.Cells(i, dateCol).Value = Round((a - b) / a, 3)
                    ws2.Cells(i, dateCol).NumberFormat = "0.0%"
                End If
            End If
        Next dateCol
        
        ' 步骤9:计算合计通过率
        If c > 0 Then
            ws2.Cells(i, 4).Value = Round((c - d) / c, 3)
            ws2.Cells(i, 4).NumberFormat = "0.0%"
        End If
        
        ' 步骤13-16:计算位置比例
        Dim total As Long
        total = upCount + midCount + downCount + fullCount
        If total > 0 Then
            ws2.Cells(i, 39).Value = Round(upCount / total, 3) ' AM列
            ws2.Cells(i, 40).Value = Round(midCount / total, 3) ' AN列
            ws2.Cells(i, 41).Value = Round(downCount / total, 3) ' AO列
            ws2.Cells(i, 42).Value = Round(fullCount / total, 3) ' AP列
            
            ' 设置百分比格式
            For j = 39 To 42
                ws2.Cells(i, j).NumberFormat = "0.0%"
            Next j
        End If
    Next i
    
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
    
    MsgBox "分析完成!", vbInformation
End Sub

4.镜筒通过率圈数分析


Option Explicit

Sub AnalyzeLensPassRate()
    Dim ws1 As Worksheet, ws2 As Worksheet
    Dim lastRow1 As Long, lastRow2 As Long
    Dim startDate As Date, endDate As Date
    Dim dict As Object, key As String
    Dim i As Long, j As Long, k As Long
    Dim dateCol As Long
    Dim a As Long, b As Long, c As Long, d As Long
    Dim posCount As Long
    
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    
    Set ws1 = Worksheets("测试记录")
    Set ws2 = Worksheets("镜筒通过率圈数分析")
    Set dict = CreateObject("Scripting.Dictionary")
    
    ' 步骤0:清除旧数据
    ws2.Range("A3:AL1000").ClearContents
    
    ' 获取日期范围
    startDate = ws2.Range("L1").Value
    endDate = ws2.Range("P1").Value
    
    ' 步骤1:提取不重复的机种和件号组合
    lastRow1 = ws1.Cells(ws1.Rows.count, "A").End(xlUp).Row
    k = 3 ' 从第3行开始写入
    
    For i = 3 To lastRow1
        If ws1.Cells(i, 1).Value >= startDate And ws1.Cells(i, 1).Value <= endDate Then
            If ws1.Cells(i, 8).Value < 800 Then
                key = ws1.Cells(i, 7).Value & "|" & ws1.Cells(i, 8).Value
                If Not dict.exists(key) Then
                    dict.Add key, k
                    ws2.Cells(k, 2).Value = ws1.Cells(i, 7).Value ' 机种
                    ws2.Cells(k, 3).Value = ws1.Cells(i, 8).Value ' 件号
                    k = k + 1
                End If
            End If
        End If
    Next i
    
    ' 步骤2:填充客户工艺
    lastRow2 = ws2.Cells(ws2.Rows.count, "B").End(xlUp).Row
    For i = 3 To lastRow2
        For j = 3 To lastRow1
            If ws1.Cells(j, 1).Value >= startDate And ws1.Cells(j, 1).Value <= endDate Then
                If ws1.Cells(j, 7).Value = ws2.Cells(i, 2).Value And _
                   ws1.Cells(j, 8).Value = ws2.Cells(i, 3).Value Then
                    ws2.Cells(i, 1).Value = ws1.Cells(j, 18).Value ' 客户工艺
                    Exit For
                End If
            End If
        Next j
    Next i
    
    ' 步骤3:排序
    With ws2.Sort
        .SortFields.Clear
        .SortFields.Add key:=Range("A3:A" & lastRow2), SortOn:=xlSortOnValues, Order:=xlAscending
        .SortFields.Add key:=Range("B3:B" & lastRow2), SortOn:=xlSortOnValues, Order:=xlAscending
        .SetRange Range("A3:AP" & lastRow2)
        .Header = xlNo
        .Apply
    End With
    
    ' 步骤4-12:计算各项指标
    For i = 3 To lastRow2
        ' 初始化合计数据
        c = 0
        d = 0
        
        ' 遍历日期列
        For dateCol = 5 To 35 ' E到AI列
            If ws2.Cells(2, dateCol).Value >= startDate And ws2.Cells(2, dateCol).Value <= endDate Then
                ' 初始化每日数据
                a = 0
                b = 0
                
                ' 遍历测试记录
                For j = 3 To lastRow1
                    If ws1.Cells(j, 1).Value = ws2.Cells(2, dateCol).Value Then
                        If ws1.Cells(j, 7).Value = ws2.Cells(i, 2).Value And _
                           ws1.Cells(j, 8).Value = ws2.Cells(i, 3).Value Then
                            ' 步骤4/7:总测试数(整罩计3)
                            a = a + 3
                            c = c + 3
                            
                            ' 步骤5/8:NG数(按位置计数)
                            If ws1.Cells(j, 11).Value = "NG" Then
                                posCount = 0
                                If InStr(ws1.Cells(j, 14).Value, "上") > 0 Then posCount = posCount + 1
                                If InStr(ws1.Cells(j, 14).Value, "中") > 0 Then posCount = posCount + 1
                                If InStr(ws1.Cells(j, 14).Value, "下") > 0 Then posCount = posCount + 1
                                If InStr(ws1.Cells(j, 14).Value, "整罩") > 0 Then posCount = posCount + 3
                                
                                b = b + posCount
                                d = d + posCount
                                
                                ' 步骤10-12:特定异常项目计数(含位置计数)
                                If InStr(ws1.Cells(j, 12).Value, "LAB") > 0 Then
                                    ws2.Cells(i, 36).Value = ws2.Cells(i, 36).Value + posCount ' AJ列
                                End If
                                If InStr(ws1.Cells(j, 12).Value, "膜色") > 0 Then
                                    ws2.Cells(i, 37).Value = ws2.Cells(i, 37).Value + posCount ' AK列
                                End If
                                If InStr(ws1.Cells(j, 12).Value, "反射率") > 0 Then
                                    ws2.Cells(i, 38).Value = ws2.Cells(i, 38).Value + posCount ' AL列
                                End If
                            End If
                        End If
                    End If
                Next j
                
                ' 步骤6:计算每日通过率
                If a > 0 Then
                    ws2.Cells(i, dateCol).Value = Round((a - b) / a, 3)
                    ws2.Cells(i, dateCol).NumberFormat = "0.0%"
                End If
            End If
        Next dateCol
        
        ' 步骤9:计算合计通过率
        If c > 0 Then
            ws2.Cells(i, 4).Value = Round((c - d) / c, 3)
            ws2.Cells(i, 4).NumberFormat = "0.0%"
        End If
    Next i
    
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
    
    MsgBox "镜筒通过率圈数分析完成!", vbInformation
End Sub

5.镜筒通过率罩次分析


Option Explicit

Sub AnalyzeLensPassRate()
    Dim ws1 As Worksheet, ws2 As Worksheet
    Dim lastRow1 As Long, lastRow2 As Long
    Dim startDate As Date, endDate As Date
    Dim dict As Object, key As String
    Dim i As Long, j As Long, k As Long
    Dim dateCol As Long
    Dim a As Long, b As Long, c As Long, d As Long
    Dim upCount As Long, midCount As Long, downCount As Long, fullCount As Long
    
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    
    Set ws1 = Worksheets("测试记录")
    Set ws2 = Worksheets("镜筒通过率罩次分析")
    Set dict = CreateObject("Scripting.Dictionary")
    
    ' 清除旧数据
    ws2.Range("A3:AP1000").ClearContents
    
    ' 获取日期范围
    startDate = ws2.Range("L1").Value
    endDate = ws2.Range("P1").Value
    
    ' 步骤1:提取不重复的机种和件号组合
    lastRow1 = ws1.Cells(ws1.Rows.count, "A").End(xlUp).Row
    k = 3 ' 从第3行开始写入
    
    For i = 3 To lastRow1
        If ws1.Cells(i, 1).Value >= startDate And ws1.Cells(i, 1).Value <= endDate Then
            If ws1.Cells(i, 8).Value < 800 Then
                key = ws1.Cells(i, 7).Value & "|" & ws1.Cells(i, 8).Value
                If Not dict.exists(key) Then
                    dict.Add key, k
                    ws2.Cells(k, 2).Value = ws1.Cells(i, 7).Value ' 机种
                    ws2.Cells(k, 3).Value = ws1.Cells(i, 8).Value ' 件号
                    k = k + 1
                End If
            End If
        End If
    Next i
    
    ' 步骤2:填充客户工艺
    lastRow2 = ws2.Cells(ws2.Rows.count, "B").End(xlUp).Row
    For i = 3 To lastRow2
        For j = 3 To lastRow1
            If ws1.Cells(j, 1).Value >= startDate And ws1.Cells(j, 1).Value <= endDate Then
                If ws1.Cells(j, 7).Value = ws2.Cells(i, 2).Value And _
                   ws1.Cells(j, 8).Value = ws2.Cells(i, 3).Value Then
                    ws2.Cells(i, 1).Value = ws1.Cells(j, 18).Value ' 客户工艺
                    Exit For
                End If
            End If
        Next j
    Next i
    
    ' 步骤3:排序
    With ws2.Sort
        .SortFields.Clear
        .SortFields.Add key:=Range("A3:A" & lastRow2), SortOn:=xlSortOnValues, Order:=xlAscending
        .SortFields.Add key:=Range("B3:B" & lastRow2), SortOn:=xlSortOnValues, Order:=xlAscending
        .SetRange Range("A3:AP" & lastRow2)
        .Header = xlNo
        .Apply
    End With
    
    ' 步骤4-16:计算各项指标
    For i = 3 To lastRow2
        ' 初始化合计数据
        c = 0
        d = 0
        upCount = 0
        midCount = 0
        downCount = 0
        fullCount = 0
        
        ' 遍历日期列
        For dateCol = 5 To 35 ' E到AI列
            If ws2.Cells(2, dateCol).Value >= startDate And ws2.Cells(2, dateCol).Value <= endDate Then
                ' 初始化每日数据
                a = 0
                b = 0
                
                ' 遍历测试记录
                For j = 3 To lastRow1
                    If ws1.Cells(j, 1).Value = ws2.Cells(2, dateCol).Value Then
                        If ws1.Cells(j, 7).Value = ws2.Cells(i, 2).Value And _
                           ws1.Cells(j, 8).Value = ws2.Cells(i, 3).Value Then
                            ' 步骤4/7:总测试数
                            a = a + 1
                            c = c + 1
                            
                            ' 步骤5/8:NG数
                            If ws1.Cells(j, 11).Value = "NG" Then
                                b = b + 1
                                d = d + 1
                                
                                ' 步骤10-12:特定异常项目计数
                                If InStr(ws1.Cells(j, 12).Value, "LAB") > 0 Then
                                    ws2.Cells(i, 36).Value = ws2.Cells(i, 36).Value + 1 ' AJ列
                                End If
                                If InStr(ws1.Cells(j, 12).Value, "膜色") > 0 Then
                                    ws2.Cells(i, 37).Value = ws2.Cells(i, 37).Value + 1 ' AK列
                                End If
                                If InStr(ws1.Cells(j, 12).Value, "反射率") > 0 Then
                                    ws2.Cells(i, 38).Value = ws2.Cells(i, 38).Value + 1 ' AL列
                                End If
                                
                                ' 步骤13-16:位置统计
                                If InStr(ws1.Cells(j, 14).Value, "上") > 0 Then upCount = upCount + 1
                                If InStr(ws1.Cells(j, 14).Value, "中") > 0 Then midCount = midCount + 1
                                If InStr(ws1.Cells(j, 14).Value, "下") > 0 Then downCount = downCount + 1
                                If InStr(ws1.Cells(j, 14).Value, "整罩") > 0 Then fullCount = fullCount + 1
                            End If
                        End If
                    End If
                Next j
                
                ' 步骤6:计算每日通过率
                If a > 0 Then
                    ws2.Cells(i, dateCol).Value = Round((a - b) / a, 3)
                    ws2.Cells(i, dateCol).NumberFormat = "0.0%"
                End If
            End If
        Next dateCol
        
        ' 步骤9:计算合计通过率
        If c > 0 Then
            ws2.Cells(i, 4).Value = Round((c - d) / c, 3)
            ws2.Cells(i, 4).NumberFormat = "0.0%"
        End If
        
        ' 步骤13-16:计算位置比例
        Dim total As Long
        total = upCount + midCount + downCount + fullCount
        If total > 0 Then
            ws2.Cells(i, 39).Value = Round(upCount / total, 3) ' AM列
            ws2.Cells(i, 40).Value = Round(midCount / total, 3) ' AN列
            ws2.Cells(i, 41).Value = Round(downCount / total, 3) ' AO列
            ws2.Cells(i, 42).Value = Round(fullCount / total, 3) ' AP列
            
            ' 设置百分比格式
            For j = 39 To 42
                ws2.Cells(i, j).NumberFormat = "0.0%"
            Next j
        End If
    Next i
    
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
    
    MsgBox "分析完成!", vbInformation
End Sub

6.客户工艺匹配


Sub MatchProcessAndClient()
    Dim ws1 As Worksheet, ws2 As Worksheet
    Dim lastRow1 As Long, lastRow2 As Long
    Dim dict As Object, key As String
    Dim notFoundList As String
    Dim i As Long
    
    ' 设置工作表对象
    Set ws1 = Worksheets("测试记录")
    Set ws2 = Worksheets("工艺&客户整理")
    Set dict = CreateObject("Scripting.Dictionary")
    
    ' 构建机种件号字典
    lastRow2 = ws2.Cells(ws2.Rows.count, "A").End(xlUp).Row
    For i = 3 To lastRow2
        key = ws2.Cells(i, 1).Value & "|" & ws2.Cells(i, 2).Value
        If Not dict.exists(key) Then
            dict.Add key, Array(ws2.Cells(i, 3).Value, ws2.Cells(i, 4).Value)
        End If
    Next i
    
    ' 匹配数据并填充
    lastRow1 = ws1.Cells(ws1.Rows.count, "G").End(xlUp).Row
    notFoundList = ""
    
    For i = 3 To lastRow1
        key = ws1.Cells(i, 7).Value & "|" & ws1.Cells(i, 8).Value
        If dict.exists(key) Then
            ' 匹配成功,填充工艺和客户
            ws1.Cells(i, 18).Value = dict(key)(0) 'R列客户工艺
            ws1.Cells(i, 19).Value = dict(key)(1) 'S列客户
        Else
            ' 未匹配,填充提示信息
            ws1.Cells(i, 18).Value = "请维护该机种工艺"
            ws1.Cells(i, 19).Value = "请维护该机种客户"
            notFoundList = notFoundList & key & vbCrLf
        End If
    Next i
    
    ' 显示未匹配项
    If notFoundList <> "" Then
        MsgBox "以下机种&件号未找到匹配项:" & vbCrLf & notFoundList, vbInformation, "匹配结果"
    Else
        MsgBox "所有机种&件号均匹配成功!", vbInformation, "匹配结果"
    End If
End Sub

7.整体通过率


Sub CalculateTestStats()
    Dim ws1 As Worksheet, ws2 As Worksheet
    Dim lastRow As Long, i As Long, j As Long
    Dim dateRange As Range, cell As Range
    Dim totalCount As Long, okCount As Long, ngCount As Long
    Dim labCount As Long, colorCount As Long, reflectCount As Long
    Dim posCount As Long, totalPosCount As Long
    Dim labPosCount As Long, colorPosCount As Long, reflectPosCount As Long
    
    ' 设置工作表引用
    Set ws1 = Worksheets("测试记录")
    Set ws2 = Worksheets("整体通过率")
    Set dateRange = ws2.Range("E2:AI2")
    
    ' 清空结果区域
    ws2.Range("E3:AI16").ClearContents
    ws2.Range("D3:D16").ClearContents
    ws2.Range("E19:AI32").ClearContents
    ws2.Range("D19:D32").ClearContents
    
    ' 获取最后数据行
    lastRow = ws1.Cells(ws1.Rows.count, 1).End(xlUp).Row
    
    ' 主统计循环
    For Each cell In dateRange
        ' 1. 统计总测试批次
        totalCount = Application.CountIf(ws1.Columns(1), cell.Value)
        ws2.Cells(3, cell.Column).Value = IIf(totalCount = 0, "", totalCount)
        
        ' 2. 统计OK批次
        okCount = Application.CountIfs(ws1.Columns(1), cell.Value, ws1.Columns(11), "OK")
        ws2.Cells(4, cell.Column).Value = IIf(okCount = 0, "", okCount)
        
        ' 3. 统计NG批次
        ngCount = Application.CountIfs(ws1.Columns(1), cell.Value, ws1.Columns(11), "NG")
        ws2.Cells(5, cell.Column).Value = IIf(ngCount = 0, "", ngCount)
        
        ' 4. 计算流通率
        If totalCount > 0 And okCount > 0 Then
            ws2.Cells(6, cell.Column).Value = Format(okCount / totalCount, "0.0%")
        Else
            ws2.Cells(6, cell.Column).Value = ""
        End If
        
        ' 5. 统计各类异常
        labCount = 0: colorCount = 0: reflectCount = 0
        posCount = 0: totalPosCount = 0
        labPosCount = 0: colorPosCount = 0: reflectPosCount = 0
        
        For i = 3 To lastRow
            If ws1.Cells(i, 1).Value = cell.Value Then
                If ws1.Cells(i, 11).Value = "NG" Then
                    ' 5.1 Lab异常
                    If InStr(1, ws1.Cells(i, 12).Value, "LAB") > 0 Then
                        labCount = labCount + 1
                        ' 14. Lab异常且位置异常
                        posCount = GetPositionCount(ws1.Cells(i, 14).Value)
                        labPosCount = labPosCount + posCount
                    End If
                    
                    ' 5.2 膜色异常
                    If InStr(1, ws1.Cells(i, 12).Value, "膜色") > 0 Then
                        colorCount = colorCount + 1
                        ' 15. 膜色异常且位置异常
                        posCount = GetPositionCount(ws1.Cells(i, 14).Value)
                        colorPosCount = colorPosCount + posCount
                    End If
                    
                    ' 5.3 反射率异常
                    If InStr(1, ws1.Cells(i, 12).Value, "反射率") > 0 Then
                        reflectCount = reflectCount + 1
                        ' 16. 反射率异常且位置异常
                        posCount = GetPositionCount(ws1.Cells(i, 14).Value)
                        reflectPosCount = reflectPosCount + posCount
                    End If
                    
                    ' 12. 位置异常统计
                    posCount = GetPositionCount(ws1.Cells(i, 14).Value)
                    totalPosCount = totalPosCount + posCount
                End If
            End If
        Next
        
        ' 输出各类异常统计结果
        ws2.Cells(7, cell.Column).Value = IIf(labCount = 0, "", labCount)        ' Lab异常
        ws2.Cells(8, cell.Column).Value = IIf(colorCount = 0, "", colorCount)    ' 膜色异常
        ws2.Cells(9, cell.Column).Value = IIf(reflectCount = 0, "", reflectCount) ' 反射率异常
        
        ' 10. 总测试数×3
        ws2.Cells(10, cell.Column).Value = IIf(totalCount = 0, "", totalCount * 3)
        
        ' 11. (总测试数×3) - 位置异常字数
        ws2.Cells(11, cell.Column).Value = IIf(totalCount = 0, "", (totalCount * 3) - totalPosCount)
        
        ' 12. 位置异常字数
        ws2.Cells(12, cell.Column).Value = IIf(totalPosCount = 0, "", totalPosCount)
        
        ' 13. 计算通过率 (D11/D10)
        If ws2.Cells(10, cell.Column).Value <> 0 And ws2.Cells(11, cell.Column).Value <> "" Then
            ws2.Cells(13, cell.Column).Value = Format(ws2.Cells(11, cell.Column).Value / ws2.Cells(10, cell.Column).Value, "0.0%")
        Else
            ws2.Cells(13, cell.Column).Value = ""
        End If
        
        ' 14-16. 输出带位置信息的异常统计
        ws2.Cells(14, cell.Column).Value = IIf(labPosCount = 0, "", labPosCount)      ' Lab异常+位置
        ws2.Cells(15, cell.Column).Value = IIf(colorPosCount = 0, "", colorPosCount)  ' 膜色异常+位置
        ws2.Cells(16, cell.Column).Value = IIf(reflectPosCount = 0, "", reflectPosCount) ' 反射率异常+位置
    Next
    
    ' 计算各列的合计值
    ws2.Range("D3").Value = Application.Sum(ws2.Range("E3:AI3"))    ' 总测试批次
    ws2.Range("D4").Value = Application.Sum(ws2.Range("E4:AI4"))    ' OK批次
    ws2.Range("D5").Value = Application.Sum(ws2.Range("E5:AI5"))    ' NG批次
    
    ' 计算总流通率
    If ws2.Range("D3").Value <> 0 And ws2.Range("D4").Value <> 0 Then
        ws2.Range("D6").Value = Format(ws2.Range("D4").Value / ws2.Range("D3").Value, "0.0%")
    Else
        ws2.Range("D6").Value = ""
    End If
    
    ws2.Range("D7").Value = Application.Sum(ws2.Range("E7:AI7"))    ' Lab异常
    ws2.Range("D8").Value = Application.Sum(ws2.Range("E8:AI8"))    ' 膜色异常
    ws2.Range("D9").Value = Application.Sum(ws2.Range("E9:AI9"))    ' 反射率异常
    ws2.Range("D10").Value = ws2.Range("D3").Value * 3              ' 总测试数×3
    
    ' 计算总位置异常字数
    totalPosCount = 0
    For i = 3 To lastRow
        If ws1.Cells(i, 11).Value = "NG" Then
            totalPosCount = totalPosCount + GetPositionCount(ws1.Cells(i, 14).Value)
        End If
    Next
    ws2.Range("D12").Value = IIf(totalPosCount = 0, "", totalPosCount)
    
    ' 计算(D11) = (D10) - (D12)
    ws2.Range("D11").Value = ws2.Range("D10").Value - ws2.Range("D12").Value
    
    ' 计算总通过率 (D11/D10)
    If ws2.Range("D10").Value <> 0 And ws2.Range("D11").Value <> "" Then
        ws2.Range("D13").Value = Format(ws2.Range("D11").Value / ws2.Range("D10").Value, "0.0%")
    Else
        ws2.Range("D13").Value = ""
    End If
    
    ' 计算带位置信息的异常合计
    ws2.Range("D14").Value = Application.Sum(ws2.Range("E14:AI14"))  ' Lab异常+位置
    ws2.Range("D15").Value = Application.Sum(ws2.Range("E15:AI15"))  ' 膜色异常+位置
    ws2.Range("D16").Value = Application.Sum(ws2.Range("E16:AI16"))  ' 反射率异常+位置
    
    ' 主统计循环
    For Each cell In dateRange
        ' 1. 统计总测试批次(H列<800)
        totalCount = 0
        For i = 3 To lastRow
            If ws1.Cells(i, 1).Value = cell.Value And ws1.Cells(i, 8).Value < 800 Then
                totalCount = totalCount + 1
            End If
        Next
        ws2.Cells(19, cell.Column).Value = IIf(totalCount = 0, "", totalCount)
        
        ' 2. 统计OK批次(H列<800)
        okCount = 0
        For i = 3 To lastRow
            If ws1.Cells(i, 1).Value = cell.Value And ws1.Cells(i, 8).Value < 800 And ws1.Cells(i, 11).Value = "OK" Then
                okCount = okCount + 1
            End If
        Next
        ws2.Cells(20, cell.Column).Value = IIf(okCount = 0, "", okCount)
        
        ' 3. 统计NG批次(H列<800)
        ngCount = 0
        For i = 3 To lastRow
            If ws1.Cells(i, 1).Value = cell.Value And ws1.Cells(i, 8).Value < 800 And ws1.Cells(i, 11).Value = "NG" Then
                ngCount = ngCount + 1
            End If
        Next
        ws2.Cells(21, cell.Column).Value = IIf(ngCount = 0, "", ngCount)
        
        ' 4. 计算流通率
        If totalCount > 0 And okCount > 0 Then
            ws2.Cells(22, cell.Column).Value = Format(okCount / totalCount, "0.0%")
        Else
            ws2.Cells(22, cell.Column).Value = ""
        End If
        
        ' 5. 统计各类异常(H列<800)
        labCount = 0: colorCount = 0: reflectCount = 0
        posCount = 0: totalPosCount = 0
        
        For i = 3 To lastRow
            If ws1.Cells(i, 1).Value = cell.Value And ws1.Cells(i, 8).Value < 800 And ws1.Cells(i, 11).Value = "NG" Then
                ' 5.1 Lab异常
                If InStr(1, ws1.Cells(i, 12).Value, "LAB") > 0 Then
                    labCount = labCount + 1
                End If
                
                ' 5.2 膜色异常
                If InStr(1, ws1.Cells(i, 12).Value, "膜色") > 0 Then
                    colorCount = colorCount + 1
                End If
                
                ' 5.3 反射率异常
                If InStr(1, ws1.Cells(i, 12).Value, "反射率") > 0 Then
                    reflectCount = reflectCount + 1
                End If
                
                ' 位置异常统计
                posCount = GetPositionCount(ws1.Cells(i, 14).Value)
                totalPosCount = totalPosCount + posCount
            End If
        Next
        
        ' 输出各类异常统计结果
        ws2.Cells(23, cell.Column).Value = IIf(labCount = 0, "", labCount)
        ws2.Cells(24, cell.Column).Value = IIf(colorCount = 0, "", colorCount)
        ws2.Cells(25, cell.Column).Value = IIf(reflectCount = 0, "", reflectCount)
        
        ' 6. 总测试数×3
        ws2.Cells(26, cell.Column).Value = IIf(totalCount = 0, "", totalCount * 3)
        
        ' 7. (总测试数×3) - 位置异常字数
        ws2.Cells(27, cell.Column).Value = IIf(totalCount = 0, "", (totalCount * 3) - totalPosCount)
        
        ' 8. 位置异常字数
        ws2.Cells(28, cell.Column).Value = IIf(totalPosCount = 0, "", totalPosCount)
        
        ' 9. 计算通过率 (D27/D26)
        If ws2.Cells(26, cell.Column).Value <> 0 And ws2.Cells(27, cell.Column).Value <> "" Then
            ws2.Cells(29, cell.Column).Value = Format(ws2.Cells(27, cell.Column).Value / ws2.Cells(26, cell.Column).Value, "0.0%")
        Else
            ws2.Cells(29, cell.Column).Value = ""
        End If
        
        ' 10. 带位置信息的异常统计
        'Dim labPosCount As Long, colorPosCount As Long, reflectPosCount As Long
        labPosCount = 0: colorPosCount = 0: reflectPosCount = 0
        
        For i = 3 To lastRow
            If ws1.Cells(i, 1).Value = cell.Value And ws1.Cells(i, 8).Value < 800 And ws1.Cells(i, 11).Value = "NG" Then
                posCount = GetPositionCount(ws1.Cells(i, 14).Value)
                
                ' 10.1 Lab异常+位置
                If InStr(1, ws1.Cells(i, 12).Value, "LAB") > 0 And posCount > 0 Then
                    labPosCount = labPosCount + posCount
                End If
                
                ' 10.2 膜色异常+位置
                If InStr(1, ws1.Cells(i, 12).Value, "膜色") > 0 And posCount > 0 Then
                    colorPosCount = colorPosCount + posCount
                End If
                
                ' 10.3 反射率异常+位置
                If InStr(1, ws1.Cells(i, 12).Value, "反射率") > 0 And posCount > 0 Then
                    reflectPosCount = reflectPosCount + posCount
                End If
            End If
        Next
        
        ws2.Cells(30, cell.Column).Value = IIf(labPosCount = 0, "", labPosCount)
        ws2.Cells(31, cell.Column).Value = IIf(colorPosCount = 0, "", colorPosCount)
        ws2.Cells(32, cell.Column).Value = IIf(reflectPosCount = 0, "", reflectPosCount)
    Next
    
    ' 计算各列的合计值
    ws2.Range("D19").Value = Application.Sum(ws2.Range("E19:AI19"))
    ws2.Range("D20").Value = Application.Sum(ws2.Range("E20:AI20"))
    ws2.Range("D21").Value = Application.Sum(ws2.Range("E21:AI21"))
    
    ' 计算总流通率
    If ws2.Range("D19").Value <> 0 And ws2.Range("D20").Value <> 0 Then
        ws2.Range("D22").Value = Format(ws2.Range("D20").Value / ws2.Range("D19").Value, "0.0%")
    Else
        ws2.Range("D22").Value = ""
    End If
    
    ws2.Range("D23").Value = Application.Sum(ws2.Range("E23:AI23"))
    ws2.Range("D24").Value = Application.Sum(ws2.Range("E24:AI24"))
    ws2.Range("D25").Value = Application.Sum(ws2.Range("E25:AI25"))
    ws2.Range("D26").Value = ws2.Range("D19").Value * 3
    
    ' 计算总位置异常字数
    totalPosCount = 0
    For i = 3 To lastRow
        If ws1.Cells(i, 8).Value < 800 And ws1.Cells(i, 11).Value = "NG" Then
            totalPosCount = totalPosCount + GetPositionCount(ws1.Cells(i, 14).Value)
        End If
    Next
    ws2.Range("D28").Value = IIf(totalPosCount = 0, "", totalPosCount)
    
    ' 计算(D27) = (D26) - (D28)
    ws2.Range("D27").Value = ws2.Range("D26").Value - ws2.Range("D28").Value
    
    ' 计算总通过率 (D27/D26)
    If ws2.Range("D26").Value <> 0 And ws2.Range("D27").Value <> "" Then
        ws2.Range("D29").Value = Format(ws2.Range("D27").Value / ws2.Range("D26").Value, "0.0%")
    Else
        ws2.Range("D29").Value = ""
    End If
    
    ' 计算带位置信息的异常合计
    ws2.Range("D30").Value = Application.Sum(ws2.Range("E30:AI30"))
    ws2.Range("D31").Value = Application.Sum(ws2.Range("E31:AI31"))
    ws2.Range("D32").Value = Application.Sum(ws2.Range("E32:AI32"))
    
    
    MsgBox "数据统计完成!", vbInformation
End Sub

Function GetPositionCount(posText As String) As Long
    Dim count As Long
    count = 0
    If InStr(1, posText, "上") > 0 Then count = count + 1
    If InStr(1, posText, "中") > 0 Then count = count + 1
    If InStr(1, posText, "下") > 0 Then count = count + 1
    If InStr(1, posText, "整罩") > 0 Then count = count + 3
    GetPositionCount = count
End Function

总结

分享:
接受可以让我面对所有的问题,当我感到焦虑的时候,通常是因为我发现自己不能接受生活中的一些人、地方、事情,直到我完全接受了它们,我才能获得心灵上的安宁。除非我完全的接受生活,否则我将无法获得快乐。我不需要再纠结这个世界上有什么需要改变而是关注我自己的态度需要发生怎样的改变;