分享

简单聊聊“先进先出”式出货的问题

 hercules028 2019-05-28

后台有人问先进先出式出货的问题……

先说一下,我们这里说的先进先出,不是数据结构上的队列……就只是一种就事论事——

百度是这么说的,先进先出是根据先入库先发出的原则,对于发出的存货以先入库存货的单价计算发出存货成本的方法……

这事看起来很复杂,代码实现起来……简单。

举个例子。

下图是一份库存表。

B列是产品名称,D列是单价,C列是进货数量,E列是已出库的数量,F列是实际存货的数量……

下图是一张出货单。本着没事就偷懒的原则,这张出货单星光模拟的极其简陋,没有出货日期,也没有出货单号……

假设咱们现在出货的产品名称是:星光牌印钞机,出货数据量是150……

那咱们就要去库存表里找星光牌印钞机了……

在第3行找到了一条记录,可惜存货量为0,没用,继续向下找……

在第4行又找到了一条记录,只有23个,先拿过来,此时我们还需要150-23=127个星光牌印钞机……

在第9行又找到了一条记录,有144个,用不了这么多,拿过来127就够了,剩下的录入结余数……

所以计算完成后的出货单是下面这样子。

库存表就变成了酱紫:

把以上找星光牌印钞机的过程用VBA代码描述下来就好了。

动图如下:

代码如下:

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那点数据,效率也不会差到哪里去……能解决问题就好。

比如,倘若是多品项先进先出法出货,如果想思路简单,那就再套一个循环一个个计算每个品项……当然啦,你如果了解字典,也可以用字典。但从解决问题的角度,那不是必须的。

4,示例文件下载:

https://pan.baidu.com/s/1u4VY87g0M4ZQ5XGVF1bvKQ 

提取码:ekq3

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约