ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
楼主: gjj136138139

[求助] Bom嵌套展开到末级(计算材料用)

[复制链接]

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-1-2 15:19 | 显示全部楼层
注意嵌套层级,要的是末级材料。就是查找材料时,它没有子级。是不是得先把材料的haschild先生成,再循环到haschild=false时终止。

计算材料20230402.zip

19.27 KB, 下载次数: 10

TA的精华主题

TA的得分主题

发表于 2024-1-2 15:34 | 显示全部楼层
gjj136138139 发表于 2024-1-2 15:15
加一层级,数就不对。得重新再生成一个字典。

什么意思
是不是你加的编码不统一原因
image.png

评分

2

查看全部评分

TA的精华主题

TA的得分主题

发表于 2024-1-2 15:41 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2024-1-2 17:49 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2024-1-2 21:38 | 显示全部楼层

递归很不擅长,感觉每次都是瞎写一通靠运气,都以为要写不出来了,不知道怎么结果好像对了
Q2A$$JNDZ9}A~COT{_2O(1P.png
20240102_212419.rar (36.26 KB, 下载次数: 4)

TA的精华主题

TA的得分主题

发表于 2024-1-2 22:21 | 显示全部楼层
本帖最后由 opiona 于 2024-1-2 23:24 编辑

递归解决BOM无限嵌套的问题
https://club.excelhome.net/thread-1445694-1-1.html


如果是展开 则需求数量=1
QQ14885553.rar (28 KB, 下载次数: 18)

核心代码:   不限制层级
  1. '*********************************
  2. '*******  北极狐工作室出品  ******
  3. '*******  QQ:14885553      ******
  4. '*********************************
  5. Option Explicit  '//强制声明变量

  6. Dim BRX, ZBC, ZBD, PRX, ZPD
  7. Dim INTX As Long
  8. Dim StrPA As String

  9. Sub A_BOM拆解()
  10.    
  11.     Dim Path As String
  12.     Dim WB As Workbook
  13.     Dim SHX, SHD, SHN, SHT As Worksheet
  14.     Dim I, X, ICOL, IROW, MAXROW, MAXCOL As Long
  15.     Dim ARX, CRX, ERX, ZCC
  16.    
  17.     Rem 禁止系统刷屏?触发其他事件等
  18.     'On Error Resume Next    '// 发生错误,自动执行下一句,就是忽略错误
  19.     Application.ScreenUpdating = False '//关闭屏幕刷新
  20.     Application.DisplayAlerts = False '//关闭系统提示
  21.     Application.EnableEvents = False  '//禁止触发其他事件
  22.     Application.StatusBar = True   '关闭系统状态条
  23.     Rem Application.Calculation = xlManual     '//xlCalculationManual  用户请求时进行计算
  24.    
  25.     Dim T
  26.     T = Timer   '//开始时间
  27.    
  28.    
  29.     Rem 获取BOM文件 或者BOM的全部数据到 全局变量: BRX
  30.     Set SHD = Worksheets("BOM")
  31.     SHD.AutoFilterMode = False  '//取消筛选
  32.     MAXCOL = SHD.Range("IT1").End(xlToLeft).Column
  33.     Set ZBC = CreateObject("Scripting.Dictionary")
  34.     For ICOL = 1 To MAXCOL
  35.         ZBC(SHD.Cells(1, ICOL).Value) = ICOL
  36.     Next
  37.     MAXROW = SHD.Range(SHD.Cells(SHD.Rows.Count, ZBC("商品编码")).Address).End(3).Row
  38.     BRX = SHD.Range("A1:" & SHD.Cells(MAXROW, MAXCOL).Address).Value
  39.    
  40.     Rem 判断ID是否存在下一层
  41.     Set ZBD = CreateObject("Scripting.Dictionary")
  42.     For X = 2 To UBound(BRX, 1)
  43.         If ZBD.EXISTS("" & BRX(X, ZBC("商品编码"))) = False Then
  44.             ZBD("" & BRX(X, ZBC("商品编码"))) = X
  45.         Else
  46.             ZBD("" & BRX(X, ZBC("商品编码"))) = ZBD("" & BRX(X, ZBC("商品编码"))) & "," & X
  47.         End If
  48.     Next
  49.     ERX = ZBD.KEYS
  50.    
  51.     Rem 初始化公共变量 保存结果 PRX
  52.     INTX = 0
  53.     ReDim PRX(1 To 3, 1 To 1)    '//输出结果数组,需转置
  54.     Set ZPD = CreateObject("Scripting.Dictionary")     '//记录那些ID已经存在 就直接相加
  55.    
  56.     Rem 开始了!
  57.     For X = 0 To UBound(ERX)
  58.         Rem 调用函数 父件+数量
  59.         StrPA = ERX(X)
  60.         Call GETBOM(ERX(X), 1)
  61.     Next
  62.    
  63.     Rem 最终结果转置
  64.     ARX = TransposeTWO(PRX)
  65.    
  66.     Rem 粘贴数据
  67.     Set SHT = Worksheets("结果表")
  68.     SHT.Select
  69.     SHT.Rows("2:" & SHT.Rows.Count).ClearContents
  70.     SHT.Range("A2").Resize(UBound(ARX, 1), UBound(ARX, 2)) = ARX
  71.    
  72.     Rem Application.Calculation = xlAutomatic  '//xlCalculationAutomaticExcel 控制重新计算。
  73.     Application.StatusBar = False   '恢复系统状态条
  74.     Application.EnableEvents = True  '//  '//恢复触发其他事件
  75.     Application.ScreenUpdating = True '//恢复屏幕刷新
  76.     Application.DisplayAlerts = True '//恢复系统提示
  77.     MsgBox "一共用时:" & Format(Timer - T, "#0.0000") & " 秒", , "北极狐QQ:14885553"  '//提示所用时间
  78.    
  79. End Sub


  80. Sub GETBOM(ByVal StrID As String, ByVal DOU As Double)
  81.     Dim X, IROW As Long
  82.     Dim StrB As String
  83.     Dim FRX
  84.    
  85.     Rem BOM表父件中查找此ID
  86.     FRX = Split(ZBD(StrID), ",")
  87.     For X = 0 To UBound(FRX)
  88.             If ZBD.EXISTS("" & BRX(Val(FRX(X)), ZBC("材料编码"))) Then
  89.                 Rem 如果还有下一层,则:万恶的递归开始了
  90.                 Call GETBOM("" & BRX(Val(FRX(X)), ZBC("材料编码")), Val(BRX(Val(FRX(X)), ZBC("标准用量"))) * DOU)
  91.             Else
  92.                 Rem 判断结果数组PRX中是否存在此ID
  93.                 StrB = "" & StrPA & BRX(Val(FRX(X)), ZBC("材料编码"))
  94.                 If ZPD(StrB) Then
  95.                     
  96.                 Else
  97.                     Rem  结果数组中不存在此ID,则增加一个ID
  98.                     INTX = INTX + 1
  99.                     ZPD(StrB) = INTX
  100.                     ReDim Preserve PRX(1 To UBound(PRX, 1), 1 To INTX)
  101.                     PRX(1, INTX) = StrPA
  102.                     PRX(2, INTX) = "" & BRX(Val(FRX(X)), ZBC("材料编码"))
  103.                 End If
  104.                                   Rem 用量
  105.                     IROW = ZPD(StrB)
  106.                     PRX(3, IROW) = Val(PRX(3, IROW)) + Val(BRX(Val(FRX(X)), ZBC("标准用量"))) * DOU     '//百分比要除:100,用量则不需要
  107.             End If
  108.     Next

  109. End Sub
复制代码



TA的精华主题

TA的得分主题

发表于 2024-1-2 22:33 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2024-1-3 09:32 来自手机 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖最后由 zpy2 于 2024-1-3 09:33 编辑
gjj136138139 发表于 2024-1-2 15:01
数据库的话,比较麻烦,好多人电脑上都没法装。我希望是vba写出来的代码直接在office环境下解决问题。vba ...


https://club.excelhome.net/thread-1613315-1-1.html?_dsign=52c4ed06

select * from bom需求计算;with recursive under_alice(子,单耗,需求) as (select 子,单耗,需求 from bom需求计算 where 需求 not like "" union select x.子,x.单耗,x.单耗*under_alice.需求 from bom需求计算 x join under_alice on x.父 =under_alice.子)select 子,sum(需求) from under_alice group by 子;

在线sql,web版sqlite支持递归查询

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-1-3 21:07 | 显示全部楼层

d(x)(z) = d(x)(z) + d(x)(y) * d(y)(z)  '这一句太牛了,新增了x和z对应的key(字典)--即在d(x)中增加了key为z,并带上了item值,为父和子的用量相乘--表示成x和z之间的用料       d(x).Remove y: ky = 1 '这是个做标记,好退出递归循环?因为后面有If ky = 0 Then Exit Sub,不是太理解这个ky。

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-1-3 21:30 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
x-xx-xx 发表于 2024-1-2 21:38
递归很不擅长,感觉每次都是瞎写一通靠运气,都以为要写不出来了,不知道怎么结果好像对了

哥们儿,我虽然不太会写代码,但是我知道代码不能这么写,你要改变一下儿,这么写代码,写的人会累死,看的也会累死的。写代码的目的是减少工作量,说白了,模块的目的就自动处理重复工作,就是用好循环来解决问题。怎么把父的换算率通过sub带到下一层去。还没写好,但至少有点递归的样子。我的想法是用redim preserve动态数组来存储结果。

Dim n As Long
Dim Brr()
Sub main()
Dim BomArr
BomArr = Sheet1.[A2:D16]
For i = LBound(BomArr) To UBound(BomArr)
    Spread i, BomArr(i, 1), BomArr, BomArr(i, 4), BomArr(i, 3), ""
Next i
Stop
Brr = Application.Transpose(Brr)
Sheets("tmp").[a2].Resize(UBound(Brr), UBound(Brr, 2)) = Brr
End Sub
Sub Spread(ByVal Index As Long, ByVal parentStr As String, ByVal Arr, ByVal isEnd As String, ByVal k As Long, ByVal varStr As String)
'Dim iStart As Long
'Dim n As Long
'Dim Brr()
Stop
MsgBox Index
MsgBox k

    If isEnd = "否" Then
        iStart = firstI(Arr(Index, 2), Arr)
        Stop
        MsgBox iStart
        MsgBox Arr(iStart, 1)
        MsgBox Arr(iStart, 4)
        Spread iStart, Arr(iStart, 1), Arr, Arr(iStart, 3), Arr(iStart, 4), ""
    Else
        n = n + 1
        ReDim Preserve Brr(1 To 4, 1 To n)
'        MsgBox parentStr
'        MsgBox Index
'        MsgBox n
            Brr(1, n) = Arr(Index, 1)
            Brr(2, n) = Arr(Index, 2)
            Brr(3, n) = Arr(Index, 3)
            Brr(4, n) = Arr(Index, 4)
            If Index = UBound(Arr) Then
            Exit Sub
            End If
            Spread Index + 1, Arr(Index + 1, 1), Arr, Arr(iStart, 3), Arr(Index + 1, 4), ""
'            Stop
    End If
End Sub
Function firstI(ByVal tmpS As String, ByVal Arr As Variant)
Dim i As Long
Dim iIndex As Long
For i = LBound(Arr) To UBound(Arr)
    If Arr(i, 1) = tmpS Then
        iIndex = i
        firstI = iIndex
        Exit Function
    End If
Next i

End Function


您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-19 13:44 , Processed in 0.042546 second(s), 14 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表