feat: implement inventory comparison worksheet for component materials
All checks were successful
NTFY Notification / notify (push) Successful in 5s
All checks were successful
NTFY Notification / notify (push) Successful in 5s
Add new "库存比对" worksheet that displays component inventory status alongside material requirements for production planning. Changes: - M04_Config: Add INVENTORY_COMPARISON_SHEET_NAME constant - M08_ComponentProcessor: Enhance component processing to return both component and sub-components when inventory insufficient; add GetComponentInventoryInfo() read-only function for inventory lookup - M09_BOMExtractor: Add WriteInventoryComparisonResults() function to generate inventory comparison worksheet with 7 columns showing material code, name, required quantity, stock quantity, and status Output format: - Columns: 序号, 生产订单号, 物料编码, 物料名称, 所需数量, 库存数量, 库存充足 - Color coding: Green (sufficient) / Red (insufficient) - Sequence numbering: 10+0, 10+1 per order Backward compatibility: Existing BOM提取结果 and BIP上传 worksheets remain unchanged. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -177,6 +177,17 @@ Public Function RunBOMExtraction() As String
|
||||
GoTo ExitHandler
|
||||
End If
|
||||
|
||||
' 步骤5.6: 生成库存比对工作表
|
||||
Application.StatusBar = "正在生成库存比对数据..."
|
||||
|
||||
Dim wsInventoryCompare As Worksheet
|
||||
Set wsInventoryCompare = WriteInventoryComparisonResults(allResults, inputModels)
|
||||
|
||||
If wsInventoryCompare Is Nothing Then
|
||||
RunBOMExtraction = "错误:无法生成库存比对工作表。"
|
||||
GoTo ExitHandler
|
||||
End If
|
||||
|
||||
' 步骤6: 生成错误报告
|
||||
If g_Logger.HasIssues Then
|
||||
g_Logger.PrintReport ActiveWorkbook
|
||||
@@ -205,9 +216,10 @@ Public Function RunBOMExtraction() As String
|
||||
Dim msg As String
|
||||
msg = "BOM提取完成!" & vbCrLf & _
|
||||
"处理型号数: " & totalModels & vbCrLf & _
|
||||
"提取物料数: " & allResults.count & vbCrLf & _
|
||||
"提取物料数: " & allResults.Count & vbCrLf & _
|
||||
"成功数: " & successCount & vbCrLf & _
|
||||
"异常数: " & errorCount
|
||||
"异常数: " & errorCount & vbCrLf & _
|
||||
"已生成库存比对工作表"
|
||||
|
||||
If g_Logger.HasErrors Then
|
||||
msg = msg & vbCrLf & vbCrLf & "发现错误,已生成错误报告工作表。"
|
||||
@@ -1364,6 +1376,266 @@ ErrorHandler:
|
||||
Set WriteBIPUploadResults = Nothing
|
||||
End Function
|
||||
|
||||
' ------------------------------------------------------------------------------
|
||||
' 写入库存比对数据到工作表
|
||||
'
|
||||
' 输入:
|
||||
' results - 提取结果集合(来自BOM提取结果)
|
||||
' inputModels - 输入数据数组(包含订单号、型号、数量、产品编码)
|
||||
'
|
||||
' 输出:
|
||||
' Worksheet - 库存比对工作表
|
||||
'
|
||||
' 逻辑:
|
||||
' 1. 创建或清空"库存比对"工作表
|
||||
' 2. 写入表头(7列)
|
||||
' 3. 遍历results,筛选materialType="部件"的物料
|
||||
' 4. 对每个部件物料:
|
||||
' a. 查找订单数量
|
||||
' b. 调用M08_ComponentProcessor.GetComponentInventoryInfo()
|
||||
' c. 计算序号
|
||||
' d. 填充行数据
|
||||
' 5. 批量写入数据
|
||||
' 6. 格式化工作表(边框、列宽)
|
||||
'
|
||||
' 输出格式(7列):
|
||||
' 1: 序号(10+0, 10+1, 20+0, 20+1...)
|
||||
' 2: 生产订单号
|
||||
' 3: 物料编码
|
||||
' 4: 物料名称
|
||||
' 5: 所需数量(订单数量 × BOM数量)
|
||||
' 6: 库存数量
|
||||
' 7: 库存充足("是"/"否")
|
||||
' ------------------------------------------------------------------------------
|
||||
Private Function WriteInventoryComparisonResults( _
|
||||
ByVal results As Collection, _
|
||||
ByVal inputModels As Variant _
|
||||
) As Worksheet
|
||||
On Error GoTo ErrorHandler
|
||||
|
||||
Dim ws As Worksheet
|
||||
Dim headers As Variant
|
||||
Dim c As Long
|
||||
Dim modelToOrderMap As Object
|
||||
Dim i As Long
|
||||
Dim j As Long
|
||||
Dim result As Variant
|
||||
Dim orderNo As String
|
||||
Dim modelStr As String
|
||||
Dim componentResults As Collection
|
||||
Dim materialType As String
|
||||
Dim outputArr() As Variant
|
||||
Dim baseSeqNum As Long
|
||||
Dim materialSeqNum As Long
|
||||
Dim currentOrderNo As String
|
||||
Dim prevOrderNo As String
|
||||
Dim resultOrderNo As String
|
||||
Dim finalSeqNum As Long
|
||||
Dim orderQty As Long
|
||||
Dim materialCode As String
|
||||
Dim materialName As String
|
||||
Dim bomQty As Long
|
||||
Dim invInfo As Object
|
||||
Dim stockQty As Long
|
||||
Dim isSufficientStr As String
|
||||
Dim requiredQty As Long
|
||||
Dim suffStatus As String
|
||||
|
||||
' 创建或获取工作表
|
||||
On Error Resume Next
|
||||
Set ws = ThisWorkbook.Sheets(INVENTORY_COMPARISON_SHEET_NAME)
|
||||
On Error GoTo ErrorHandler
|
||||
|
||||
If ws Is Nothing Then
|
||||
Set ws = ThisWorkbook.Worksheets.Add(After:=ActiveWorkbook.Sheets(ActiveWorkbook.Sheets.Count))
|
||||
ws.Name = INVENTORY_COMPARISON_SHEET_NAME
|
||||
Else
|
||||
ws.Cells.Clear
|
||||
End If
|
||||
|
||||
' 写入表头(7列)
|
||||
headers = Array("序号", "生产订单号", "物料编码", "物料名称", "所需数量", "库存数量", "库存充足")
|
||||
|
||||
For c = 1 To 7
|
||||
ws.Cells(1, c).Value = headers(c - 1)
|
||||
Next c
|
||||
|
||||
' 格式化表头
|
||||
With ws.Range("A1:G1")
|
||||
.Font.Bold = True
|
||||
.Interior.Color = RGB(217, 217, 217)
|
||||
.HorizontalAlignment = xlCenter
|
||||
End With
|
||||
|
||||
' ========================================
|
||||
' 步骤1: 构建产品型号 → 生产订单号的映射
|
||||
' ========================================
|
||||
' 在BOM提取结果中,result(1)(生产订单号)仅第一行有值,
|
||||
' 但result(2)(原始产品型号)每行都有值
|
||||
' 因此需要建立映射:产品型号 → 生产订单号
|
||||
|
||||
Set modelToOrderMap = CreateObject("Scripting.Dictionary")
|
||||
|
||||
For i = 1 To results.Count
|
||||
result = results(i)
|
||||
|
||||
orderNo = CStr(result(1)) ' 第1列:生产订单号
|
||||
modelStr = CStr(result(2)) ' 第2列:原始产品型号
|
||||
|
||||
' 仅当订单号不为空时,添加映射
|
||||
If Len(Trim(orderNo)) > 0 And Len(Trim(modelStr)) > 0 Then
|
||||
If Not modelToOrderMap.Exists(modelStr) Then
|
||||
modelToOrderMap.Add modelStr, orderNo
|
||||
End If
|
||||
End If
|
||||
Next i
|
||||
|
||||
' ========================================
|
||||
' 步骤2: 筛选"部件"类型物料
|
||||
' ========================================
|
||||
Set componentResults = New Collection
|
||||
|
||||
For i = 1 To results.Count
|
||||
result = results(i)
|
||||
|
||||
' 第9列是物料类型
|
||||
materialType = CStr(result(9))
|
||||
|
||||
' 仅处理"部件"类型
|
||||
If materialType = "部件" Then
|
||||
componentResults.Add result
|
||||
End If
|
||||
Next i
|
||||
|
||||
' 写入数据
|
||||
If componentResults.Count > 0 Then
|
||||
' 先设置物料编码列(第3列,C列)为文本格式
|
||||
ws.Range("C2:C" & (componentResults.Count + 1)).NumberFormat = "@"
|
||||
|
||||
' 准备输出数组
|
||||
ReDim outputArr(1 To componentResults.Count, 1 To 7)
|
||||
|
||||
' 序号生成变量
|
||||
baseSeqNum = 0
|
||||
materialSeqNum = 0
|
||||
currentOrderNo = ""
|
||||
prevOrderNo = ""
|
||||
|
||||
' ========================================
|
||||
' 步骤3: 写入库存比对数据
|
||||
' ========================================
|
||||
For i = 1 To componentResults.Count
|
||||
result = componentResults(i)
|
||||
|
||||
' 【关键修复】从映射表中获取订单号
|
||||
modelStr = CStr(result(2)) ' 第2列:原始产品型号
|
||||
|
||||
If modelToOrderMap.Exists(modelStr) Then
|
||||
resultOrderNo = CStr(modelToOrderMap(modelStr))
|
||||
Else
|
||||
resultOrderNo = ""
|
||||
End If
|
||||
|
||||
' 检测新订单
|
||||
If resultOrderNo <> prevOrderNo And Len(Trim(resultOrderNo)) > 0 Then
|
||||
prevOrderNo = resultOrderNo
|
||||
currentOrderNo = resultOrderNo
|
||||
baseSeqNum = baseSeqNum + 10
|
||||
materialSeqNum = 0
|
||||
End If
|
||||
|
||||
' 计算序号:基数 + 物料序号
|
||||
finalSeqNum = baseSeqNum + materialSeqNum
|
||||
materialSeqNum = materialSeqNum + 1
|
||||
|
||||
' 查找订单数量(使用currentOrderNo)
|
||||
orderQty = 1 ' 默认值
|
||||
|
||||
For j = LBound(inputModels, 1) To UBound(inputModels, 1)
|
||||
If CStr(inputModels(j, 1)) = currentOrderNo Then
|
||||
orderQty = CLng(inputModels(j, 3)) ' 第3列是订单数量
|
||||
Exit For
|
||||
End If
|
||||
Next j
|
||||
|
||||
' 提取物料信息
|
||||
materialCode = CStr(result(11)) ' 第11列:物料编码
|
||||
materialName = CStr(result(10)) ' 第10列:物料名称
|
||||
|
||||
' 第12列:BOM库基础数量
|
||||
If IsNumeric(result(12)) Then
|
||||
bomQty = CLng(result(12))
|
||||
Else
|
||||
bomQty = 1
|
||||
End If
|
||||
|
||||
' 获取库存信息
|
||||
Set invInfo = M08_ComponentProcessor.GetComponentInventoryInfo( _
|
||||
materialCode, bomQty, orderQty)
|
||||
|
||||
' 提取库存数据
|
||||
stockQty = invInfo("stockQty")
|
||||
isSufficientStr = IIf(invInfo("isSufficient"), "是", "否")
|
||||
|
||||
' 计算所需数量
|
||||
requiredQty = orderQty * bomQty
|
||||
|
||||
' 填充输出数组
|
||||
outputArr(i, 1) = finalSeqNum ' 序号
|
||||
outputArr(i, 2) = currentOrderNo ' 【关键修复】生产订单号
|
||||
outputArr(i, 3) = materialCode ' 物料编码
|
||||
outputArr(i, 4) = materialName ' 物料名称
|
||||
outputArr(i, 5) = requiredQty ' 所需数量
|
||||
outputArr(i, 6) = stockQty ' 库存数量
|
||||
outputArr(i, 7) = isSufficientStr ' 库存充足
|
||||
Next i
|
||||
|
||||
' 批量写入数据
|
||||
ws.Range("A2").Resize(componentResults.Count, 7).Value = outputArr
|
||||
|
||||
' 格式化数据区域
|
||||
With ws.Range("A2:G" & (componentResults.Count + 1))
|
||||
.Borders.LineStyle = xlContinuous
|
||||
.Borders.Weight = xlThin
|
||||
End With
|
||||
|
||||
' 根据库存状态设置背景色
|
||||
For i = 1 To componentResults.Count
|
||||
suffStatus = CStr(outputArr(i, 7))
|
||||
|
||||
If suffStatus = "否" Then
|
||||
' 库存不足,标记为淡红色
|
||||
ws.Cells(i + 1, 7).Interior.Color = RGB(255, 200, 200)
|
||||
Else
|
||||
' 库存充足,标记为淡绿色
|
||||
ws.Cells(i + 1, 7).Interior.Color = RGB(200, 255, 200)
|
||||
End If
|
||||
Next i
|
||||
|
||||
' 设置列宽
|
||||
ws.Columns("A").ColumnWidth = 8 ' 序号
|
||||
ws.Columns("B").ColumnWidth = 15 ' 生产订单号
|
||||
ws.Columns("C").ColumnWidth = 15 ' 物料编码
|
||||
ws.Columns("D").ColumnWidth = 30 ' 物料名称
|
||||
ws.Columns("E").ColumnWidth = 10 ' 所需数量
|
||||
ws.Columns("F").ColumnWidth = 10 ' 库存数量
|
||||
ws.Columns("G").ColumnWidth = 10 ' 库存充足
|
||||
|
||||
' 冻结首行
|
||||
ws.Activate
|
||||
ActiveWindow.FreezePanes = False
|
||||
ws.Rows(2).Select
|
||||
ActiveWindow.FreezePanes = True
|
||||
ws.Cells(1, 1).Select
|
||||
End If
|
||||
|
||||
Set WriteInventoryComparisonResults = ws
|
||||
Exit Function
|
||||
|
||||
ErrorHandler:
|
||||
Set WriteInventoryComparisonResults = Nothing
|
||||
End Function
|
||||
|
||||
' ------------------------------------------------------------------------------
|
||||
' 打开BOM库文件
|
||||
'
|
||||
|
||||
Reference in New Issue
Block a user