来自Excel之家,侵联系删
先说一下,我们这里说的先进先出,不是数据结构上的队列……就只是一种就事论事——
百度是这么说的,先进先出是根据先入库先发出的原则,对于发出的存货以先入库存货的单价计算发出存货成本的方法……
![19933e3c9bab378b9171d1c1afb15adf.png](https://i-blog.csdnimg.cn/blog_migrate/5db59100033660dc64bdf6db87a2a3a7.jpeg)
这事看起来很复杂,代码实现起来……简单。
举个例子。
下图是一份库存表。
![56dba114eb487e86c3249867a8386880.png](https://i-blog.csdnimg.cn/blog_migrate/54e18068c899dce7f1377d89a56d66f7.jpeg)
B列是产品名称,D列是单价,C列是进货数量,E列是已出库的数量,F列是实际存货的数量……
下图是一张出货单。本着没事就偷懒的原则,这张出货单星光模拟的极其简陋,没有出货日期,也没有出货单号……
![9b5d9a52b4cf4d6b3b4bb02f926deda2.png](https://i-blog.csdnimg.cn/blog_migrate/22839ec244c5c4bcd14e4d40810fa007.jpeg)
假设咱们现在出货的产品名称是:星光牌印钞机,出货数据量是150……
那咱们就要去库存表里找星光牌印钞机了……
在第3行找到了一条记录,可惜存货量为0,没用,继续向下找……
在第4行又找到了一条记录,只有23个,先拿过来,此时我们还需要150-23=127个星光牌印钞机……
在第9行又找到了一条记录,有144个,用不了这么多,拿过来127就够了,剩下的录入结余数……
所以计算完成后的出货单是下面这样子。
![afd727ab9ca8ebbe0e414030fa5e91ab.png](https://i-blog.csdnimg.cn/blog_migrate/d468990c80a82903981ba56dbf0fcf56.jpeg)
库存表就变成了酱紫:
![5edfdd56c80b7c36b832accb591443e3.png](https://i-blog.csdnimg.cn/blog_migrate/d594ec2a71c8b91c73bd3d640b908bf5.jpeg)
把以上找星光牌印钞机的过程用VBA代码描述下来就好了。
动图如下:
![e74f847812b937e4fdffb665221c09b6.gif](https://i-blog.csdnimg.cn/blog_migrate/6595f582e7c631b30feb55240d646cda.gif)
代码如下:
Sub FirstInFirstOut()
Dim arr As Variant
Dim Pname As String
Dim Pnum As Long, i As Long, j As Long
Dim Jnum As Long, k As Long, Tnum As Long
With Sheets("出库单")
.Select
Pname = Range("b2").Value
'出货产品的名称
Pnum = Range("e2").Value
'出货产品的数量
End With
If Pname = "" Or Pnum = 0 Then MsgBox "老板,您的信息填写不完整。": Exit Sub
arr = Sheets("库存表").Range("a1").CurrentRegion
'库存表的数据装入数组arr
ReDim brr(1 To UBound(arr), 1 To 6)
'结果数组,出库单只有6列,故设置为6列。最大行数不可能超过数据源arr,故设置为arr的行数
ReDim crr(1 To UBound(arr), 1 To 1)
'用于保存每个库存表商品出库的数量
For i = 1 To UBound(arr)
If arr(i, 2) = Pname Then
'如果库存表的产品名称等于出库单产品名称
Jnum = arr(i, 6) '结存数量
If Jnum > 0 Then '如果有结存数量
k = k + 1
If Jnum >= Pnum Then '如果结存数大于目标数
brr(k, 4) = Pnum '数量
Else
brr(k, 4) = Jnum
End If
brr(k, 1) = k '序号
brr(k, 2) = arr(i, 2) '商品名称
brr(k, 3) = arr(i, 1) '进货日期
brr(k, 5) = arr(i, 4) '单价
brr(k, 6) = brr(k, 4) * brr(k, 5) '金额
crr(i, 1) = brr(k, 4)
'将出库的商品数量记录起来
Tnum = Tnum + Jnum '累加总出库数量
Pnum = Pnum - Jnum
If Pnum <= 0 Then Exit For
End If
End If
Next
If Pnum > 0 Then
MsgBox "老板,冷静,你家的货不够出了啊。" & vbCrLf & _
"库存数量:" & Tnum & vbCrLf & _
"出货数量:" & Range("e2").Value
Else
Sheets("出库单").UsedRange.Offset(3).ClearContents
Range("a4").Resize(k, UBound(brr, 2)) = brr '数据写入出库单
For i = 1 To UBound(crr)
If crr(i, 1) > 0 Then
'将出库的数量写入库存表
With Sheets("库存表").Cells(i, 5)
.Value = crr(i, 1) + .Value
End With
End If
Next
MsgBox "ok"
End If
End Sub
小贴士:
1,代码里有注释。
2,很多时候代码做的事,只是把人工做的过程直白的描述出来,特别是VBA这种简单的小程序,数据量不大,也用不到什么算法,就是换个语言叙事而已。
3,不要把问题想的复杂,循环最重要,不行就循环,把自己要的数据先挑出来再说。一个循环不够,你就再弄一个,就Excel那点数据,效率也不会差到哪里去……能解决问题就好。
![82e30371f07e58b1018c271c17795ac4.png](https://i-blog.csdnimg.cn/blog_migrate/1b6c1b1cd2f69d7194c7988d049fffa0.jpeg)
比如,倘若是多品项先进先出法出货,如果想思路简单,那就再套一个循环一个个计算每个品项……当然啦,你如果了解字典,也可以用字典。但从解决问题的角度,那不是必须的。
练习素材分享:
“素材”可以私信进了领取,点击私聊,输入“库存素材”,请用正式版今日头条