' ============================================================================== ' 模块名称: mBOMRepository ' 模块类别: 标准模块 (Standard Module) ' 所属项目: BOMForge ' 模块职责: 负责 Excel 表格与 cBOMRow 内存对象之间的双向数据交互 ' ============================================================================== Option Explicit ' ------------------------------------------------------------------------------ ' 函数名称: LoadAllBOMs ' 函数功能: 将工作表中的 BOM 数据逐行加载为 cBOMRow 对象的集合 ' 参数说明: ws - 目标工作表对象 ' ------------------------------------------------------------------------------ Public Function LoadAllBOMs(ws As Worksheet) As Collection Dim coll As New Collection Dim lastRow As Long Dim i As Long Dim rowObj As cBOMRow ' 获取 A 列最后一行 (假设 A 列总是有数据的,如行号) lastRow = ws.Cells(ws.Rows.count, "A").End(xlUp).row ' 根据业务说明,表头在第3行,数据从第4行开始 If lastRow < 4 Then Set LoadAllBOMs = coll Exit Function End If For i = 4 To lastRow Set rowObj = New cBOMRow ' 映射 Excel 列到对象属性 rowObj.ExcelRowIndex = i rowObj.RowNo = Val(ws.Cells(i, 1).value) rowObj.ModuleType = Trim(ws.Cells(i, 2).value) rowObj.Code = Trim(ws.Cells(i, 3).value) rowObj.ItemName = Trim(ws.Cells(i, 4).value) rowObj.Quantity = Val(ws.Cells(i, 5).value) rowObj.Condition = Trim(ws.Cells(i, 6).value) rowObj.Remark = Trim(ws.Cells(i, 7).value) rowObj.Category = Trim(ws.Cells(i, 8).value) rowObj.ParentCategory = Trim(ws.Cells(i, 9).value) rowObj.CategoryCondition = Trim(ws.Cells(i, 10).value) rowObj.Code66 = Trim(ws.Cells(i, 11).value) rowObj.BIPBaseRowNo = Trim(ws.Cells(i, 12).value) ' 【关键】刚从 Excel 读取的数据是原生态的,重置脏标记 rowObj.ResetDirtyFlag coll.Add rowObj Next i Set LoadAllBOMs = coll End Function ' ------------------------------------------------------------------------------ ' 函数名称: SaveAll ' 函数功能: 遍历集合,仅将发生改变 (IsDirty = True) 的对象写回 Excel ' 参数说明: ws - 目标工作表对象, bomCollection - 内存对象集合 ' ------------------------------------------------------------------------------ Public Sub SaveAll(ws As Worksheet, bomCollection As Collection) Dim rowObj As cBOMRow Dim r As Long For Each rowObj In bomCollection ' 【性能核心】只写回被业务策略修改过的行 If rowObj.IsDirty Then r = rowObj.ExcelRowIndex ' 如果是新增行,ExcelRowIndex 可能为空或需要重新计算 If r <= 0 Then r = ws.Cells(ws.Rows.count, "A").End(xlUp).row + 1 rowObj.ExcelRowIndex = r End If ' 将属性写回对应的列 ws.Cells(r, 1).value = rowObj.RowNo ws.Cells(r, 2).value = rowObj.ModuleType ws.Cells(r, 3).value = rowObj.Code ws.Cells(r, 4).value = rowObj.ItemName ws.Cells(r, 5).value = rowObj.Quantity ws.Cells(r, 6).value = rowObj.Condition ws.Cells(r, 7).value = rowObj.Remark ws.Cells(r, 8).value = rowObj.Category ws.Cells(r, 9).value = rowObj.ParentCategory ws.Cells(r, 10).value = rowObj.CategoryCondition ws.Cells(r, 11).value = rowObj.Code66 ws.Cells(r, 12).value = rowObj.BIPBaseRowNo ' 保存完毕,重置脏标记 rowObj.ResetDirtyFlag End If Next rowObj End Sub ' ------------------------------------------------------------------------------ ' 函数名称: InsertNewBOMRow ' 函数功能: 基于现有行克隆出一个新行对象,用于弹性元件等需要全新规格新增的场景 ' ------------------------------------------------------------------------------ Public Function InsertNewBOMRow(bomCollection As Collection, copyFromObj As cBOMRow) As cBOMRow Dim newObj As New cBOMRow ' 设置为 0 意味着在 SaveAll 时,它会自动追加到 Excel 的最后一行 newObj.ExcelRowIndex = 0 ' 属性克隆 newObj.RowNo = copyFromObj.RowNo ' 这里的行号往往需要外部策略重新编排,先克隆 newObj.ModuleType = copyFromObj.ModuleType newObj.Code = copyFromObj.Code ' 同样等待外部策略分配新代码 newObj.ItemName = copyFromObj.ItemName newObj.Quantity = copyFromObj.Quantity newObj.Condition = copyFromObj.Condition newObj.Remark = copyFromObj.Remark newObj.Category = copyFromObj.Category newObj.ParentCategory = copyFromObj.ParentCategory newObj.CategoryCondition = copyFromObj.CategoryCondition newObj.Code66 = copyFromObj.Code66 newObj.BIPBaseRowNo = copyFromObj.BIPBaseRowNo ' 强制触发一下脏标记,确保这个新对象会被 SaveAll 捕获写进 Excel ' 由于 Let 属性判断 <> 才会触发,我们采用一个小技巧 newObj.Code = newObj.Code & "_TEMP" newObj.Code = copyFromObj.Code bomCollection.Add newObj Set InsertNewBOMRow = newObj End Function