|
本帖最后由 opiona 于 2024-1-2 23:24 编辑
递归解决BOM无限嵌套的问题
https://club.excelhome.net/thread-1445694-1-1.html
如果是展开 则需求数量=1
QQ14885553.rar
(28 KB, 下载次数: 18)
核心代码: 不限制层级
- '*********************************
- '******* 北极狐工作室出品 ******
- '******* QQ:14885553 ******
- '*********************************
- Option Explicit '//强制声明变量
- Dim BRX, ZBC, ZBD, PRX, ZPD
- Dim INTX As Long
- Dim StrPA As String
- Sub A_BOM拆解()
-
- Dim Path As String
- Dim WB As Workbook
- Dim SHX, SHD, SHN, SHT As Worksheet
- Dim I, X, ICOL, IROW, MAXROW, MAXCOL As Long
- Dim ARX, CRX, ERX, ZCC
-
- Rem 禁止系统刷屏?触发其他事件等
- 'On Error Resume Next '// 发生错误,自动执行下一句,就是忽略错误
- Application.ScreenUpdating = False '//关闭屏幕刷新
- Application.DisplayAlerts = False '//关闭系统提示
- Application.EnableEvents = False '//禁止触发其他事件
- Application.StatusBar = True '关闭系统状态条
- Rem Application.Calculation = xlManual '//xlCalculationManual 用户请求时进行计算
-
- Dim T
- T = Timer '//开始时间
-
-
- Rem 获取BOM文件 或者BOM的全部数据到 全局变量: BRX
- Set SHD = Worksheets("BOM")
- SHD.AutoFilterMode = False '//取消筛选
- MAXCOL = SHD.Range("IT1").End(xlToLeft).Column
- Set ZBC = CreateObject("Scripting.Dictionary")
- For ICOL = 1 To MAXCOL
- ZBC(SHD.Cells(1, ICOL).Value) = ICOL
- Next
- MAXROW = SHD.Range(SHD.Cells(SHD.Rows.Count, ZBC("商品编码")).Address).End(3).Row
- BRX = SHD.Range("A1:" & SHD.Cells(MAXROW, MAXCOL).Address).Value
-
- Rem 判断ID是否存在下一层
- Set ZBD = CreateObject("Scripting.Dictionary")
- For X = 2 To UBound(BRX, 1)
- If ZBD.EXISTS("" & BRX(X, ZBC("商品编码"))) = False Then
- ZBD("" & BRX(X, ZBC("商品编码"))) = X
- Else
- ZBD("" & BRX(X, ZBC("商品编码"))) = ZBD("" & BRX(X, ZBC("商品编码"))) & "," & X
- End If
- Next
- ERX = ZBD.KEYS
-
- Rem 初始化公共变量 保存结果 PRX
- INTX = 0
- ReDim PRX(1 To 3, 1 To 1) '//输出结果数组,需转置
- Set ZPD = CreateObject("Scripting.Dictionary") '//记录那些ID已经存在 就直接相加
-
- Rem 开始了!
- For X = 0 To UBound(ERX)
- Rem 调用函数 父件+数量
- StrPA = ERX(X)
- Call GETBOM(ERX(X), 1)
- Next
-
- Rem 最终结果转置
- ARX = TransposeTWO(PRX)
-
- Rem 粘贴数据
- Set SHT = Worksheets("结果表")
- SHT.Select
- SHT.Rows("2:" & SHT.Rows.Count).ClearContents
- SHT.Range("A2").Resize(UBound(ARX, 1), UBound(ARX, 2)) = ARX
-
- Rem Application.Calculation = xlAutomatic '//xlCalculationAutomaticExcel 控制重新计算。
- Application.StatusBar = False '恢复系统状态条
- Application.EnableEvents = True '// '//恢复触发其他事件
- Application.ScreenUpdating = True '//恢复屏幕刷新
- Application.DisplayAlerts = True '//恢复系统提示
- MsgBox "一共用时:" & Format(Timer - T, "#0.0000") & " 秒", , "北极狐QQ:14885553" '//提示所用时间
-
- End Sub
- Sub GETBOM(ByVal StrID As String, ByVal DOU As Double)
- Dim X, IROW As Long
- Dim StrB As String
- Dim FRX
-
- Rem BOM表父件中查找此ID
- FRX = Split(ZBD(StrID), ",")
- For X = 0 To UBound(FRX)
- If ZBD.EXISTS("" & BRX(Val(FRX(X)), ZBC("材料编码"))) Then
- Rem 如果还有下一层,则:万恶的递归开始了
- Call GETBOM("" & BRX(Val(FRX(X)), ZBC("材料编码")), Val(BRX(Val(FRX(X)), ZBC("标准用量"))) * DOU)
- Else
- Rem 判断结果数组PRX中是否存在此ID
- StrB = "" & StrPA & BRX(Val(FRX(X)), ZBC("材料编码"))
- If ZPD(StrB) Then
-
- Else
- Rem 结果数组中不存在此ID,则增加一个ID
- INTX = INTX + 1
- ZPD(StrB) = INTX
- ReDim Preserve PRX(1 To UBound(PRX, 1), 1 To INTX)
- PRX(1, INTX) = StrPA
- PRX(2, INTX) = "" & BRX(Val(FRX(X)), ZBC("材料编码"))
- End If
- Rem 用量
- IROW = ZPD(StrB)
- PRX(3, IROW) = Val(PRX(3, IROW)) + Val(BRX(Val(FRX(X)), ZBC("标准用量"))) * DOU '//百分比要除:100,用量则不需要
- End If
- Next
-
- End Sub
复制代码
|
|