DAX实现先入先出法

本文介绍了如何使用DAX(Data Analysis Expressions)在Power BI或Excel中实现先进先出(FIFO)库存计算方法。通过筛选入库记录,计算结余数量对应的结余金额,涉及步骤包括筛选构成结余数量的入库记录,计算归属结余的入库金额,以及得出出库金额。最终,通过实例展示了计算过程的正确性。
摘要由CSDN通过智能技术生成

思路:

(文末附有文件下载链接)

如果先计算出累计入库数量与累计出库数量,然后为每一笔出库的数量匹配到相应的入库批次,这样计算量显然过大。

在先进先出法下,可以认为结余数量是由最后入库的几批构成的。计算结余数量对应的结余金额则比较简单。

如示例数据中,产品B的第10行,剩余的380件应当包含3月20日的80件,3月5日的70件,2月11日的150件,与2月1日的80件。所以这380件的结余金额为3月20日的16000元+3月5日的21000元+2月11日的24000+2月1日的48000*(80/200),等于80200元。

实现:

要计算出上文的80200元,则需要首先删选原表,以删选出可以构成剩余数量380的那几行入库记录。再为其中部分入库的那一行(最早的那一行),按比例计算出归属于结余金额的部分(48000/200*80)。即,需要构建出上图所示的表格。

想要构建上表,则需要先筛选出2月11日、3月5日、3月20日这三行。再筛选出2月1日这一行,并将其中的200改为80(40%),然后入库金额也相应改为40%,19200元。

2月11日、3月5日、3月20日这三行即从下往上累计入库数量,累计数量不超过结余数量(380)的那些行。可以构建下图所示的表格,再对表格进行筛选后得到。

有了初步的思路,现在可以开始用DAX来实现这个想法了。

步骤一:

首先,删选出[入库数量]不为空,产品为当前产品,发生时序不晚于当前行时序(index小于等于当前的index)的部分。然后为前一步删选出的表格,增加一列计算列[不足数量](即,从下往上累计的入库数量少于结存数量的量)。要实现从下往上累加,也就是对Index大于当前迭代的index的行进行求和。再对上面的结果进行筛选,筛选出[不足数量]大于等于0的部分,就是上文所说的“2月11日、3月5日、3月20日这三行即从下往上累计入库数量,累计数量不超过结余数量(380)的那些行”。因为在单元格内,无法直接显示一张张的表,所以对计算表的[入库数量]列进行求和,以检验结果是否正确。

添加计算列**[步骤一检验数]**

步骤一检验数 = 
VAR vRest= 'F02先进先出法'[结余数量]
VAR vName='F02先进先出法'[名称]
VAR vNum='F02先进先出法'[index]
VAR vCumDiff=
    ADDCOLUMNS(
        FILTER(
            ALL('F02先进先出法'),
            'F02先进先出法'[名称]=vName
            	&&'F02先进先出法'[index]<=vNum
            	&& not ISBLANK('F02先进先出法'[入库数量])
        ),
        //删选了[入库数量]不为空,产品为当前产品,发生时序不晚于当前行时序(index小于当前的index)的部分
        "不足数量",
        VAR vNumInner='F02先进先出法'[index]
        RETURN 
        vRest-
            SUMX(   //实现从下往上累加[入库数量]
                FILTER(
                    ALL('F02先进先出法'),
                    'F02先进先出法'[名称]=vName&&'F02先进先出法'[index]<=vNum&&'F02先进先出法'[index]>=vNumInner
                ),
                [入库数量]
            )
    )
VAR vAllIn=
    FILTER(
        vCumDiff,
        [不足数量]>=0
    ) //筛选出了入库数量全归于结余数量的行
VAR vAllInQuantity=SUMX(vAllIn,[入库数量])  //对[入库数量]求和,以便检查是否正确。
RETURN
    vAllInQuantity

检查结果,最后第一行300=80+70+150,最后第二行500=80+70+150+200,最后第3行420=70+150+200。第一步的结果是正确。

步骤二:

以计算产品B第10行的结余金额为例,到现在我们已经求得了下面的三行。还缺最上面的那行,部分归入结余数量的那行。

以计算产品B第10行的结余金额为例,[步骤一检验数] 中的表格变量vCumDiff 如下图所示。我们需要那一行就是不足数量<0的行中,不足数量最大的那一行。

使用TOPN筛选出该行,因为不能显示表,所以计算出该行[日期]列的值,以检验是否正确。在步骤一的计算下添加以下代码,以实现筛选该行,并找出[日期]进行检验。

VAR vPartIn=
    TOPN(
        1,
        FILTER(
            vCumDiff,
            [不足数量]<0
        ),
        [不足数量],
        DESC
    )
VAR test=SELECTCOLUMNS(vPartIn,"A",'F02先进先出法'[入库数量])
RETURN
    test

检验无误。

步骤三:

以计算产品B第10行的结余金额为例。接下来计算步骤一筛选出的3行中的入库金额,与步骤二筛选出的1行中应该归入结余金额的部分入库金额。

VAR vAllInAmount=
    SUMX(
        vAllIn,
        [入库金额]
    )  //示例中的3行对应的金额
//归属结余的数量乘以入库单价,即为归属于结余的金额
VAR vPartInAmount= SELECTCOLUMNS(vPartIn,"A",[入库单价])*(vRest-vAllInQuantity)
VAR vRestAmount=vAllInAmount + vPartInAmount
RETURN
    vRestAmount

检验无误。至此,[步骤一检验数] [步骤二检验数] 这两个计算列就可以删除了。

步骤四:

[入库金额]与[结余金额]都已经有了,现在还缺出库金额。计算出库金额可以使用出库前,也就是出库行的上一行的结余金额,减于出库后的结余金额而得。

出库金额 = 
VAR vName='F02先进先出法'[名称]
VAR vNum='F02先进先出法'[index]
VAR vAmount=
    SELECTCOLUMNS(
        FILTER(
            ALL('F02先进先出法'),
            'F02先进先出法'[名称]=vName
                &&'F02先进先出法'[index]=vNum-1
        ),
        "A",
        'F02先进先出法'[结余金额]
    )-'F02先进先出法'[结余金额]
RETURN 
    IF( 
        NOT ISBLANK('F02先进先出法'[出库数量]),
        vAmount
    )

附件下载:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值