扩展vlookup以计算商品成本

时间:2018-01-15 05:59:51

标签: excel excel-vba excel-formula vba

我有电子商店的销售报告,需要计算每个订单行的商品成本。订单行可能看起来像其中之一:

2x Lavazza Crema e Aroma 1kg - 1x Lavazza Dolce Caffe Crema 1kg

1x Lavazza Vending Aroma Top 1kg - 1x Arcaffe Roma 1Kg - 1x Kimbo - 100%Arabica Top Flavour

所以,我需要Excel做的是拿出每个产品,从另一个工作表中用vlookup函数找到它的成本,然后将它与所订购的数量相乘。问题是订购的产品数量从1到10+不等。 我试着用VBA来计算它,但是代码没有用(我现在没有使用乘法,我知道) 也许有可能用excel公式解决这个问题?

Function GoodsCost(str, Optional strDelim As String = " ")
larray = Split(str, strDelim)
Set lookup_range = Worksheets("Products").Range("B:E")
For i = LBound(larray) To UBound(larray)
    skuarray = Split(larray(i), "x ")
    skucost = Application.WorksheetFunction.VLookup(UBound(skuarray), lookup_range, 4, False)
    cost = cost + skucost
Next i
GoodsCost = cost
End Function

4 个答案:

答案 0 :(得分:0)

好吧,好像现在问题已经解决了。当然,只有在假设产品描述中不存在破折号( - )时,它才有效。但它可以在产品列表中设置。另一个机会是使用另一个分隔符(例如" /")。我们可以使用Ctrl + F查找所有组合,例如" x - "并用" x /")

替换它们
Function GoodsCost(str)
Dim answer As Double
Set Products = Worksheets("Products").Range("B:E")
larray = Split(str, " - ")
For i = LBound(larray) To UBound(larray)
    sku = Split(larray(i), "x ")
    Price = Application.WorksheetFunction.VLookup(sku(1), Products, 4, False) * sku(0)
    answer = answer + Price
Next i
GoodsCost = answer
End Function

答案 1 :(得分:0)

您可以在下面找到可在工作表中使用的UDF(用户定义函数)。在标准代码模块中安装它之后(VBE将它们命名为" Module1"),您可以从工作表中调用它,如=CostOfGoods($A2),其中A2是包含的单元格和订单行,如您所述。 / p>

Option Explicit

Function CostOfGoods(Cell As Range) As Single
    ' 15 Jan 2018

    Const Delim As String = " - "

    Dim Fun As Single                   ' function return value
    Dim Sale As Variant
    Dim Sp() As String
    Dim i As Long
    Dim PriceList As Range
    Dim Qty As Single, Price As Single
    Dim n As Integer

    Sale = Trim(Cell.Value)
    If Len(Sale) Then
        Sp = Split(Sale, Delim)
        Do While i <= UBound(Sp)
            If InStr(Sp(i), "x ") = 0 Then
                If Not ConcatSale(Sp, i, Delim) Then Exit Do
            End If
            i = i + 1
        Loop

        With Worksheets("Products")
            i = .Cells(.Rows.Count, "B").End(xlUp).Row
            ' price list starts in row 2 (change as required)
            Set PriceList = Range(.Cells(2, "B"), .Cells(i, "E"))
        End With

        For i = 0 To UBound(Sp)
            Qty = Val(Sp(i))
            n = InStr(Sp(i), " ")
            Sp(i) = Trim(Mid(Sp(i), n))
            On Error Resume Next
            Price = Application.VLookup(Sp(i), PriceList, 4, False)
            If Err Then
                MsgBox "I couldn't find the price for" & vbCr & _
                       Sp(i) & "." & vbCr & _
                       "The total cost calculated excludes this item.", _
                       vbInformation, "Price not found"
                Price = 0
            End If
            Fun = Fun + (Qty * Price)
        Next i
    End If

    CostOfGoods = Fun
End Function

Private Function ConcatSale(Sale() As String, _
                            i As Long, _
                            Delim As String) As Boolean
    ' 15 Jan 2018

    Dim Fun As Boolean                  ' function return value
    Dim x As Long, f As Long

    x = UBound(Sale)
    If (i > 0) And (i <= x) Then
        i = i - 1
        Sale(i) = Sale(i) & Delim & Sale(i + 1)
        For f = i + 1 To x - 1
            Sale(f) = Sale(f + 1)
        Next f
        Fun = True
    End If

    If Fun Then ReDim Preserve Sale(x - 1)
    ConcatSale = Fun
End Function

答案 2 :(得分:0)

我已对此进行了测试,它适用于产品说明中的破折号:

Function GoodsCost(str, Optional strDelim As String = " ")
larray = Split(str, " ")
'split the cell contents by space
Set lookup_range = Worksheets("Products").Range("B:E")
'set lookup range
For i = LBound(larray) To UBound(larray) 'loop through array
nextproduct:
    LPosition = InStr(larray(i), "x") 'find multiplier "x" in string
    If LPosition = Len(larray(i)) Then 'if the last character is x
        If Product <> "" Then GoTo lookitup 'lookup product
        Quantity = larray(i) 'get quantity
    Else
        Product = Product & " " & larray(i) 'concatenate array until we get a full product description to lookup with
    End If
Next i
lookitup:
If Right(Product, 2) = " -" Then Product = Left(Product, Len(Product) - 2)
If Left(Product, 1) = " " Then Product = Right(Product, Len(Product) - 1)
'above trim the Product description to remove unwanted spaces or dashes
cost = Application.WorksheetFunction.VLookup(Product, lookup_range, 4, False)
Quantity = Replace(Quantity, "x", "")
GoodsCost = cost * Quantity
MsgBox Product & " @ Cost: " & GoodsCost
Product = ""
If i < UBound(larray) Then GoTo nextproduct
End Function

答案 3 :(得分:0)

我使用正则表达式来解决这个问题。首先,它在字符串中找到&#39;分隔符&#39;将-替换为;仅检测-旁边的数字x后跟-(即产品名称中忽略#Value的乘数)。然后将每个结果分成数量和产品(再次使用RegEx)。然后,它会在您的数据中找到产品并返回商品成本。如果出现错误,或产品未包含在您的数据中,则会返回Public Function GoodsCost(str As String) As Double Dim lookup_range As Range, ProductMatch As Range Dim v, Match Dim qty As Long Dim prod As String Dim tmp() As String On Error GoTo err Set lookup_range = Worksheets("Products").Range("B:E") With CreateObject("vbscript.regexp") .Global = True .ignorecase = True .pattern = "(\s\-\s)(?=[0-9]+x)" If .test(str) Then tmp = Split(.Replace(str, ";"), ";") Else ReDim tmp(0) tmp(0) = str End If .pattern = "(?:([0-9]+)x\s(.+))" For Each v In tmp If .test(v) Then Set Match = .Execute(v) qty = Match.Item(0).submatches.Item(0) prod = Trim(Match.Item(0).submatches.Item(1)) Set ProductMatch = lookup_range.Columns(1).Find(prod) If Not ProductMatch Is Nothing Then GoodsCost = GoodsCost + (qty * ProductMatch.Offset(0, 3)) Else GoodsCost = CVErr(xlErrValue) End If End If Next v End With Exit Function err: GoodsCost = CVErr(xlErrValue) End Function 错误,表明存在问题。

public void postvalidUser(string UserName, string Password)
        {
            try
            {
                var login = uData.Users.Where(x => x.UserName == UserName).ToList();
                if (login != null && login.Count > 0)
                {
                    foreach (var log in login)
                    {
                        if (log.UserName == UserName && log.Password == Password)
                        {
                            Console.WriteLine("login ok");

                        }

                    }
                }
                else
                {
                   Console.WriteLine("login fail");

                }

            }

            catch (Exception ex){

                Console.WriteLine(ex);
            }

        }