Excel VBA Course
Excel VBA Course - From Beginner to Expert

200+ Video Lessons
50+ Hours of Video
200+ Excel Guides

Become a master of VBA and Macros in Excel and learn how to automate all of your tasks in Excel with this online course. (No VBA experience required.)

View Course

using Average function to populate in price column on form

0

Hi,

I would know why when using average function doesn't show me correct price!

here this is line should works for column 6 in listbox to show average price when fill brand in textbox1 based on column(D).

b(y, 6) = Format(Application.WorksheetFunction.Average(a(i, 6)), "#,##0.00")

I hope some body tell me what's the reason, what's  the correct way.

Answer
Discuss

Answers

0
Selected Answer

Hi again Leopard

Your line:

b(y, 6) = Format(Application.WorksheetFunction.Average(a(i, 6)), "#,##0.00")

doesn't make much sense- it tries to average a single number (which produces the number itself) and so it just gives a text version of that number. In fact, if there's more than one  match for a given (perhaps partial) "BRAND",  it just overwrites b(y, 6) with a text version of the last UNIT PRICE for that "BRAND"

REVISION #1, 19 February 2025

In the attached modified file, the code is changed so that:

  1.  the ListBox now:
    • includes a row of titles
    • ignores CLIENT NO and INVOICE NO columns
    • provides two average prices- see below
    • has columns adjusted manually via its ColumnWidths property
  2. it corrects an error whereby the line  y = dic(ky) incorrectly set the row.

See the changes in bold below (with comments for your understanding):

Sub FilterData()
  Dim txt1 As String, txt2 As String, txt3 As String
  Dim i As Long, j As Long, k As Long, y As Long
  Dim dic As Object
  Dim ky As Variant

  Set dic = CreateObject("Scripting.Dictionary")

  ListBox1.Clear
' add row for titles
  ReDim b(1 To UBound(a, 1) + 1, 1 To UBound(a, 2))
  ' write titles
    b(1, 1) = "Item"
    b(1, 2) = "Brand"
    b(1, 3) = "Transactions"
    b(1, 4) = "Total Quantity"
    b(1, 5) = "Total Value"
    b(1, 6) = "Average Transaction price"
    b(1, 7) = "Average Unit price"

  For i = 1 To UBound(a)
    If TextBox1 = "" Then txt1 = a(i, 4) Else txt1 = TextBox1

    If UCase(a(i, 4)) Like "*" & UCase(txt1) & "*" Then
      ky = a(i, 4)

      If Not dic.exists(ky) Then
        k = k + 1
        ' use a dictionary item counter other than y
        j = j + 1
        dic(ky) = j
      End If

      y = dic(ky)

      ' write in rows below first (titles)
      b(y + 1, 1) = y
      b(y + 1, 2) = a(i, 4) 'Brand
      b(y + 1, 3) = b(y + 1, 3) + 1 'number of transactions in this element
      b(y + 1, 4) = Format(CDec(b(y + 1, 4)) + a(i, 5), "#,##0.00") ' total Qty
      ' add to total value
      b(y + 1, 5) = Format(CDec(b(y + 1, 5)) + a(i, 5) * a(i, 6), "#,##0.00")
      ' see if this is the first price for dictionary item
      If b(y + 1, 6) = "" Then
        ' if so, just capture first price
        b(y + 1, 6) = Format(a(i, 6), "#,##0.00")
        Else
        ' otherwise convert existing entry, add to new value then calculate average
        b(y + 1, 6) = Format((CDec(b(y + 1, 6)) * (b(y + 1, 3) - 1) + a(i, 6)) / b(y + 1, 3), "#,##0.00")
      End If
      ' write unit average price
      b(y + 1, 7) = Format(CDec(b(y + 1, 5)) / CDec(b(y + 1, 4)), "#,##0.00")
    End If
  Next
 If k > 0 Then ListBox1.List = b

End Sub

This will gives both the average of the UNIT PRICE used in each matching transaction or row in your worksheet and the average price of the units sold (total price divided by total quantity- see more detail in the Discussion below this Answer).

Hope this helps.

Discuss

Discussion

Hi John
thanks for your comment and answering .
I'm afraid  still gives error result
for  BRAND 1200R20 G580 JAP =1820+1825+1830/3  should be=1818.33
but what I get 1821.25!
leopard (rep: 98) Feb 19, '25 at 8:14 am
Leopard. Thanks-I just realised my mistake (I forgot to account for the number if matches). I will correct that later today but please confirm that you are happy with the avearge price used in transactions (rather than the true  average unit price). 
John_Ru (rep: 6642) Feb 19, '25 at 8:37 am
 but please confirm that you are happy with the avearge price used in transactions (rather than the true  average unit price). 
I' m not understand what you mean. 
leopard (rep: 98) Feb 19, '25 at 8:43 am
Say I sell the same BRAND in two transactions - the first for 1 item quantity 1 at £100 and the second for quantity 20 at £80 each.

The average price per transaction is (£100+£80)/2 = £90, where 2 is the number of transactions. 

The average unit price however is
= (1*£100 + 20*£80)/(1+20)
= £1,700/21
= £80.95

Your example above (of code error) with 3 transactions is the former (rather than the average unit price) 
John_Ru (rep: 6642) Feb 19, '25 at 9:58 am
Also, in the ListBox results, you give the (last) CUSTOMER but not all transactions might be with CUSTOMER. In that column, may I instead report e.g. "3 transaction(s)"? I could then use that array element to collect the number of tranactions to use in the average.
John_Ru (rep: 6642) Feb 19, '25 at 10:18 am
@John
I was confused by leopard's coding syntax; glad you have been able to make some sense of it.
WillieD24 (rep: 657) Feb 19, '25 at 12:59 pm
sorry about columns B,C  I don't care for theses columns . I admit this is my bad shouldn't show . what I look for to  shows average price for duplicates  BRANDS in column D  . after merged QTY for each duplicates brands then will show average price  as I did above and  last column =QTY*AVERAGE PRICE.
so what's wrong about average price above?
I don't understand why is not correct as you think , John.
leopard (rep: 98) Feb 19, '25 at 2:03 pm
Leopard- please see REVISION #1, 19 February 2025 to my Answer plus the revised file.
John_Ru (rep: 6642) Feb 19, '25 at 5:24 pm
ok  the average price is right in column 6 in listbox and this what I want, but what I don't understand  when column 5 = column 4 * column 6   doesn't show right value.
ex: 1200R20 G580 JAP =130*1818.333=236,383.00
leopard (rep: 98) Feb 20, '25 at 4:29 am
Leopard. I don't think you understand the mathematics of this...

To give another example, if I sell 2 units of an item at $100 each and 8 units at $50 each, then the average price used in a transaction (column 6 of the ListBox) is ($100 + $50)/2 = $75. You refer to this above as "average price is right ... .what I want..." but that is NOT the mathematical average price since that $75 times the total quantity is (2+98)*$75 = $7,500 whereas the total selling price was 2*$100 + 98*50= $5,100. That's why the average unit price (column 7) is calculated as the total selling prIce / total quantity i.e. $5,100/(98+2) = $51 each i.e. the average is really affected by the quantites per transaction..

In the ListBox, column 7 is the Average Unit Price (so that mathematical average price of all items sold). For 1200R20 G580 JAP, column 7 gives 1,807.88 and, multiplied by the quantity, gives the total value (column 5) =130*1807.88 =235,025.00. You can check this in your worksheet
John_Ru (rep: 6642) Feb 20, '25 at 8:56 am
(continued...) 

So to be clear, column 6 of the ListBox is the average of transaction prices (irrespective of the quantities sold in each transaction). I think its only use is to say "I normally sell 1200R20 G580 JAP for about $1,818".. Otherwise it has no use I can think of.

Column 7 however is the average unit price of items sold and, when multiplied by the quantity, gives the tiotal price (though there may be small rounding ewrrors since you chose to FORMAT the values).

Hope this makes sense and you can see that my solution is correct. You may choose to remove the column 6.calculation.

Kindly read this carefully and proceed to mark my Answer as Selected.
John_Ru (rep: 6642) Feb 20, '25 at 8:57 am
I didn't think the average price method would have such a big impact that it would lead to catastrophic errors. I thought it would be close to the real values ​​when verified and the differnt will be minor , but I was really wrong!.
so I see average price function in excel is useless for accurate accounts..
thank you for your spotting about the right way .
leopard (rep: 98) Feb 20, '25 at 10:42 am
Glad you saw the problem and thanks for selecting my Answer, Leopard.

Excel's AVERAGE function isn't useless but you need to apply it correctly (and understand some of the the maths !) 
John_Ru (rep: 6642) Feb 20, '25 at 11:15 am
Add to Discussion
0

Hi leopard,

I'm not sure if this is the cause of your problem but I'm going to take a guess based on what I see with your code.

You have the variable " a " equal a range (A2:G10). You should declare "a" as a Range object and then use Set a =.

Then when the userform is initialized both TextBox1 and ListBox1 are empty. 

Then in your formula You have Average looking at A2:G10 ( a ). You should be specific and state which column you want to average (E, F, or G) - something like: Average(F2:F & Range("D" & Rows.Count).End(3), (Range("D" & Rows.Count).End(3)-1))

Hope this helps

Cheers   :-)

Discuss

Discussion

Hi Willie,
but I specify the column as in above. the column 6 in listbox will be equal column F in side sheet !
leopard (rep: 98) Feb 18, '25 at 2:34 am
Hi leopard, 
As I stated at the beginning of my response, "I'm going to take a guess". Sorry, but I don't have anything more to offer.
Maybe John will join in and provide the solution you are looking for.

Cheers   :-)
WillieD24 (rep: 657) Feb 18, '25 at 10:11 am
@Leopard

Please see my Answer

@Willie

Good try- I hope I got it right
John_Ru (rep: 6642) Feb 19, '25 at 7:46 am
@Willie - if you have chance, please read the later poarts of the Discussion under my Answer- I think Leopard is struggling with the maths of averages. It may help him if you can confirm that my "Average Unit Price" equates to the true mathematical avarage.
John_Ru (rep: 6642) Feb 20, '25 at 9:02 am
@Willie -forget that please - my second example convinced Leopard of the influence of large quantities on the average. Thanks anyway. 
John_Ru (rep: 6642) Feb 20, '25 at 11:18 am
@John
You are spot-on with the calculation of the average. It's unfortunate that leopard, at first, couldn't grasp what you were explaining. Luckily leopard finally clued in that you were right all along. It was my lack of understanding in leopard's line:
b(y, 6) = Format(Application.WorksheetFunction.Average(a(i, 6)), "#,##0.00")
that kept me from providing a solution. The variables " a " and " b " are used in the code but not declared so I made my best guess as to what they are. And when the userform loaded but was empty I kinda gave up at that point.

Once again, good work John !!

Cheers   :-)
WillieD24 (rep: 657) Feb 20, '25 at 11:45 am
@Willie - thanks. I'm away from my PC but think variable a is declared as Variant and assigned to a range (outside sub FilterData) whereas b is populated in FilterData.
John_Ru (rep: 6642) Feb 20, '25 at 1:49 pm
Add to Discussion


Answer the Question

You must create an account to use the forum. Create an Account or Login