refactor: support filtered data processing and optimize performance

- Add clear data button functionality to Sheet9
- Refactor AccessDataModule to safely handle filtered data with memory array optimization
- Refactor BIPUploadModule to process only visible rows with screen updating optimization
- Refactor ComponentInventoryCheckModule to support filtered data and improve performance
- Refactor MainModule to handle filtered data and remove '代号' field
- Add RestoreAppStatus helper for better application state management
- Improve overall performance by using memory arrays instead of cell-by-cell operations

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Misaka_Company
2026-03-13 13:12:31 +08:00
parent 596a2d0ad2
commit 36c00befa5
5 changed files with 220 additions and 112 deletions

View File

@@ -1,7 +1,7 @@
'=====================================================================
' 模块名: ComponentInventoryCheckModule
' 功能: 部件库存核模块 - 自动核对产品订单中"部件"类物料的库存情况
' 说明: 当库存不足时,按订单顺序将超出部分的订单的"部件优先"字段标记为"否"
' 功能: 部件库存核模块 - 自动核对产品订单中"部件"类物料的库存情况
' 特性: [已重构] 支持仅对筛选后的数据进行处理,采用内存极速读取
'=====================================================================
Option Explicit
@@ -43,6 +43,10 @@ Public Sub CheckComponentInventory()
Dim startTime As Double
startTime = Timer
' 提升性能:关闭屏幕更新和自动计算
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
' 获取工作表对象
Dim orderSheet As Worksheet
Dim inventorySheet As Worksheet
@@ -50,18 +54,21 @@ Public Sub CheckComponentInventory()
Set orderSheet = GetOrderSheet()
If orderSheet Is Nothing Then
RestoreAppStatus
MsgBox "未找到[产品订单]工作表!", vbExclamation
Exit Sub
End If
Set inventorySheet = GetInventorySheet()
If inventorySheet Is Nothing Then
RestoreAppStatus
MsgBox "未找到[现存量]工作表!", vbExclamation
Exit Sub
End If
Set bomSheet = GetBomSheet()
If bomSheet Is Nothing Then
RestoreAppStatus
MsgBox "未找到[平台配置清单]工作表!", vbExclamation
Exit Sub
End If
@@ -70,16 +77,30 @@ Public Sub CheckComponentInventory()
Dim lastRow As Long
lastRow = orderSheet.Cells(orderSheet.Rows.count, 3).End(xlUp).row
If lastRow < 2 Then
RestoreAppStatus
MsgBox "[产品订单]工作表没有数据!", vbExclamation
Exit Sub
End If
' 【核心重构】获取筛选后的可见单元格区域 (A列)
Dim visibleRange As Range
On Error Resume Next
Set visibleRange = orderSheet.Range("A2:A" & lastRow).SpecialCells(xlCellTypeVisible)
On Error GoTo ErrorHandler
If visibleRange Is Nothing Then
RestoreAppStatus
MsgBox "当前筛选状态下没有可见的数据。", vbInformation
Exit Sub
End If
' 初始化BOM提取器
Dim BomExtractor As BomExtractor
Set BomExtractor = New BomExtractor
BomExtractor.SetWorksheet bomSheet
If Not BomExtractor.LoadBomData Then
RestoreAppStatus
MsgBox "加载BOM数据失败:" & BomExtractor.GetErrorSummary, vbCritical
Exit Sub
End If
@@ -89,16 +110,18 @@ Public Sub CheckComponentInventory()
Set inventoryData = LoadInventoryData(inventorySheet)
If inventoryData.count = 0 Then
RestoreAppStatus
MsgBox "[现存量]工作表没有有效数据!", vbExclamation
Exit Sub
End If
' 读取订单数据
' 【核心重构】传递可见区域和总行数,仅读取可见订单数据
Dim orders As Collection
Set orders = LoadOrderData(orderSheet)
Set orders = LoadOrderData(orderSheet, visibleRange, lastRow)
If orders.count = 0 Then
MsgBox "没有有效的订单数据!", vbExclamation
RestoreAppStatus
MsgBox "可见区域中没有有效的订单数据!", vbExclamation
Exit Sub
End If
@@ -110,7 +133,8 @@ Public Sub CheckComponentInventory()
Set componentDemands = CalculateComponentDemand(orders)
If componentDemands.count = 0 Then
MsgBox "没有订单包含'部件'类别物料,无需处理库存!", vbInformation
RestoreAppStatus
MsgBox "筛选的订单中没有包含'部件'类别物料,无需处理库存!", vbInformation
Exit Sub
End If
@@ -118,17 +142,20 @@ Public Sub CheckComponentInventory()
Dim validationWarnings As Collection
Set validationWarnings = ValidateInventory(componentDemands, inventoryData)
' 按订单顺序分配库存
' 按订单顺序分配库存并标记
Dim stats As Statistics
AllocateInventory orders, componentDemands, orderSheet, stats
' 恢复应用状态
RestoreAppStatus
' 输出结果统计
Dim elapsedTime As Double
elapsedTime = Timer - startTime
Dim resultMsg As String
resultMsg = "部件库存核对完成!" & vbCrLf & vbCrLf
resultMsg = resultMsg & "处理订单数: " & stats.TotalOrders & vbCrLf
resultMsg = resultMsg & "处理筛选订单数: " & stats.TotalOrders & vbCrLf
resultMsg = resultMsg & "包含部件订单: " & stats.OrdersWithComponent & vbCrLf
resultMsg = resultMsg & "库存充足订单: " & stats.OrdersSufficient & vbCrLf
resultMsg = resultMsg & "库存不足订单: " & stats.OrdersInsufficient & vbCrLf
@@ -148,37 +175,54 @@ Public Sub CheckComponentInventory()
Exit Sub
ErrorHandler:
RestoreAppStatus
MsgBox "部件库存核对异常: " & Err.Description, vbCritical
End Sub
'=====================================================================
' 辅助过程: RestoreAppStatus
' 功能: 恢复Excel应用程序的状态
'=====================================================================
Private Sub RestoreAppStatus()
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
'=====================================================================
' 函数: LoadOrderData
' 功能: 读取订单数据
' 参数: ws - [产品订单]工作表
' 返回: Collection - 每个元素是字典对象,包含订单信息
'=====================================================================
Private Function LoadOrderData(ws As Worksheet) As Collection
Private Function LoadOrderData(ws As Worksheet, visibleRange As Range, lastRow As Long) As Collection
Set LoadOrderData = New Collection
' 调整为按C列获取最后一行
Dim lastRow As Long
lastRow = ws.Cells(ws.Rows.count, 3).End(xlUp).row
' 全量读入内存数组提升速度
Dim sourceDataArr As Variant
sourceDataArr = ws.Range("A2:F" & lastRow).value
Dim i As Long
For i = 2 To lastRow
Dim cell As Range
Dim arrIndex As Long
' 仅遍历可见的单元格
For Each cell In visibleRange
Dim model As String
Dim qty As Variant
' --- 核心修改列索引向右移1列 ---
model = Trim(ws.Cells(i, 3).value) ' C列: 产品型号 (原B列)
qty = ws.Cells(i, 4).value ' D列: 产品数量 (原C列)
' 数组索引 = Excel行号 - 1
arrIndex = cell.row - 1
' 从内存数组中提取数据
model = Trim(sourceDataArr(arrIndex, 3)) ' C列: 产品型号
qty = sourceDataArr(arrIndex, 4) ' D列: 产品数量
' 跳过空行
If model <> "" Then
Dim order As Object
Set order = CreateObject("Scripting.Dictionary")
order.Add ORDER_ROW, CLng(i)
' 记录真实的Excel行号用于后续库存不足时精准写入F列
order.Add ORDER_ROW, CLng(cell.row)
order.Add ORDER_MODEL, CStr(model)
order.Add ORDER_QUANTITY, CDbl(IIf(IsNull(qty) Or IsEmpty(qty), 0, qty))
order.Add ORDER_COMP_CODE, ""
@@ -188,7 +232,7 @@ Private Function LoadOrderData(ws As Worksheet) As Collection
LoadOrderData.Add order
End If
Next i
Next cell
End Function
'=====================================================================
@@ -327,15 +371,12 @@ Private Function ValidateInventory(componentDemands As Object, _
' 检查库存中是否存在该部件
If Not inventoryData.Exists(compInv(INV_CODE)) Then
' 库存中找不到设置库存为0并添加警告
compInv(INV_STOCK) = 0
compInv(INV_SHORTAGE) = True
ValidateInventory.Add "部件 '" & compInv(INV_CODE) & "' 在[现存量]中未找到"
Else
' 设置可用库存
compInv(INV_STOCK) = inventoryData(compInv(INV_CODE))
' 检查是否短缺
If compInv(INV_DEMAND) > compInv(INV_STOCK) Then
compInv(INV_SHORTAGE) = True
End If
@@ -402,8 +443,7 @@ Private Sub AllocateInventory(orders As Collection, _
compInv(INV_STOCK) = compInv(INV_STOCK) - requiredQty
stats.OrdersSufficient = stats.OrdersSufficient + 1
Else
' --- 核心修改回填结果写入F列(第6列) ---
' 库存不足,标记为"否"
' --- 因为已经保存了真正的行号 ORDER_ROW, 在关闭屏幕刷新的情况下,这里直接写入是非常快的 ---
orderSheet.Cells(order(ORDER_ROW), 6).value = "否"
compInv(INV_STOCK) = compInv(INV_STOCK) - requiredQty
stats.OrdersInsufficient = stats.OrdersInsufficient + 1