ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 1972|回复: 12

[分享] 按照BOM拆解需求计划

[复制链接]

TA的精华主题

TA的得分主题

发表于 2021-5-19 17:38 | 显示全部楼层 |阅读模式
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖最后由 opiona 于 2021-5-19 23:13 编辑

看到很多: 按照BOM拆解需求计划  例如:http://club.excelhome.net/thread-1585438-1-1.html
才发现原来做的递归解法 效率不是很高  于是进行了修改
发出来  供大家参考:  
附件已经简化 见2楼   可以更直观看到结果
1.png 2.png 3.png

    



代码:

  1. Option Explicit  '//强制声明变量

  2. Dim BRX, ZBC, ZBD, PRX, ZPD
  3. Dim INTX As Long

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


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

  108. Rem *************************************************************
  109. Rem 二维数组转置
  110. Rem 参数:ARR  一个二维数组
  111. Rem 输出:一个二维数组
  112. Rem 使用方法:
  113. '    Dim ARR()  '//作为参数的数组,要先声明
  114. '    ARR = Sheet1.Range("A1:B4").Value  '//赋值给数组
  115. '    BRR = TransposeTWO(ARR)   '//转置后的数组,可以不用实现声明
  116. '    CRR = Application.Transpose(FileArr)  '//转置,一维数组变成竖排
  117. Rem 北极狐工作室整理,QQ:14885553
  118. Rem *************************************************************
  119. Public Function TransposeTWO(ARR) As Variant
  120.     Dim X, Y, LB As Long
  121.     LB = LBound(ARR, 1)
  122.     ReDim ARX(LB To UBound(ARR, 2), LB To UBound(ARR, 1))
  123.    
  124.     For Y = LB To UBound(ARR, 2)
  125.         For X = LB To UBound(ARR, 1)
  126.             ARX(Y, X) = ARR(X, Y)
  127.         Next X
  128.     Next Y
  129.     TransposeTWO = ARX
  130. End Function

复制代码




BOM拆解-递归-升级版.rar

32.93 KB, 下载次数: 92

评分

2

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2021-5-19 23:09 | 显示全部楼层
附件已经简化 可以更直观看到结果
BOM拆解-递归-升级版.rar (32.93 KB, 下载次数: 81)

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2021-5-21 17:24 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
opiona 发表于 2021-5-19 23:09
附件已经简化 可以更直观看到结果

老师如果A02的下级BOM中的物料B01已经有库存两个,如何能得到正确的结果????

BOM拆解-递归-升级版(14).zip

31.33 KB, 下载次数: 18

TA的精华主题

TA的得分主题

发表于 2021-5-21 17:44 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2021-5-21 18:38 | 显示全部楼层

TA的精华主题

TA的得分主题

 楼主| 发表于 2021-5-22 13:02 | 显示全部楼层
fjwyn 发表于 2021-5-21 17:24
老师如果A02的下级BOM中的物料B01已经有库存两个,如何能得到正确的结果????

那就更复杂一些了
可以参考37楼: http://club.excelhome.net/thread-1408935-1-1.html

TA的精华主题

TA的得分主题

 楼主| 发表于 2022-11-25 13:24 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
数据多了 发现速度很慢
现在改进了递归和字典  速度提升很多

BOM递归拆解_缺料运算扣库存_字典更快.rar (187.99 KB, 下载次数: 63)

TA的精华主题

TA的得分主题

发表于 2023-9-2 17:36 | 显示全部楼层
image.jpg

BOM叶子节点用料统计by@今铭昔0902.zip

36.72 KB, 下载次数: 19

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-9-2 18:46 | 显示全部楼层
tomxie 发表于 2023-9-2 18:28
大概看了一下,VBA 代码有230行左右,如果用SQL,应当不会超过15行,时间估计大约0.1秒。

SQL对多层的BOM拆解适应性较差
以前做过SQL的有限层级的  见一楼的链接

TA的精华主题

TA的得分主题

发表于 2023-9-2 19:08 | 显示全部楼层
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-4-30 18:49 , Processed in 0.042385 second(s), 13 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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