2016-02-20 119 views
2

單元格的內容在Excel平均,我有1列與行情,以及列2號,這樣的:如何獲得通過VBA

 A B  
1 AAA 10 
2 AAA 12 
3 AAA 14 
4 BBB 9 
5 BBB 10 
6 BBB 11 

我需要一段代碼來計算平均BY TICKER,這意味着在這種情況下,我會得到AAA平均值:12和BBB平均值= 10等。等到現在我所得到的是這個代碼,它試圖計算總和,我會在稍後做分割,但是有些事情是錯誤的:

For row = 2 to 6 
Ticker = Cells(row - 1, 1) 
If Cells(row, 1) = Cells(row - 1, 1) Then 
sum = sum + Cells(row, 2) 
Else 
Cells(row, 6) = sum 
sum = 0 
row = row + 1 
Next 

我得到一個錯誤說 「對於缺少」

+0

我想你錯過了'結束如果'。 –

+4

你看過電子表格公式AVERAGEIF嗎?我認爲這可以在沒有VBA的情況下做到你所需要的。 –

+2

請參閱[AVERAGEIF](https://support.office。com/en-us/article/AVERAGEIF-function-ff3c70f9-5afe-4d3e-87d4-717187f98c20)和[AVERAGEIFS](https://support.office.com/zh-cn/article/AVERAGEIFS-function-48910C45-1FC0 -4389-A028-F7C5C3001690)功能。 – Jeeped

回答

4

在C1中可能是這樣的。

=IF(A1<>A2,AVERAGEIF(A:A,A1,B:B),"") 

averageif_once

+0

我喜歡使用'A1 <> A2'。我假設(和你一樣)原始數據是有序的。 –

+0

那麼,我們只能繼續討論OP提供的示例,並且示例數據是有序的。很多時候,樣本數據經過編輯和簡化,以使可行的解決方案永遠不會對實際數據起作用,但您必須從某處開始。 – Jeeped

+1

即使未訂購,爲了保持您的示例的外觀,您可以在C1'= AVERAGEIF(A:A,A1,B:B)'和C2'= IF(COUNTIF($ A $ 1:$ A1, A2),「」,AVERAGEIF(A:A,A2,B:B))''可以從C2拷貝下來,不是數組公式;) –

0

在您的代碼:

  • 總和忽略第一AAA
  • 錯過了結束如果
  • 遞增行兩次,一次是由行=行+ 1,然後下一個
  • 和一些其他未使用的變量

試試這個:

Prev = "***" 
For row = 1 to 6 
    If Cells(row, 1) = prev Then 
    sum = sum + Cells(row, 2) 
    Else 
    Cells(row, 6) = sum 
    sum = 0 
    End If 
    prev = Cells(row,1) 
Next 
0

爲了擴大從Jeeped答案,並與未進行排序的列表做到這一點,你也可以做這樣的:

C1:  =A1 
C2:  =IF(LEN(C1),IFERROR(INDEX(A:A,MATCH(1,(COUNTIF(C$1:C1,A$1:A$1000)=0)*(A$1:A$1000<>""),0)),""),"")} 
C3....Cn: copy down from C2 

D1:  =IF(LEN(C1),AVERAGEIF(A:A,C1,B:B),"") 
D2...Dn: copy down from D1 

C2是陣列配方,需要與確認Ctrl + Shift + Enter

要通過VBA做到這一點(應該比我的公式更快),你可以使用類似的東西:(把它放在VBA-Window中的「模塊」中,就像寫入的記錄宏一樣)

Option Explicit 

Public Function getAllAvg(rng As Range) As Variant 
    Set rng = Intersect(rng.Parent.UsedRange, rng) 

    Dim varInput As Variant 
    varInput = rng.Value 

    Dim varOutput() As Variant 
    ReDim varOutput(1 To UBound(varInput), 1 To 2) 
    varOutput(1, 1) = "" 

    Dim i As Long, j As Long 
    For i = 1 To UBound(varInput) 
    If Len(varInput(i, 1)) Then 
     j = 1 

     While Len(varOutput(j, 1)) And (varOutput(j, 1) <> varInput(i, 1)) And (j < UBound(varOutput)) 
     j = j + 1 
     Wend 

     If Len(varOutput(j, 1)) = 0 Then 
     varOutput(j, 1) = varInput(i, 1) 
     varOutput(j, 2) = Application.AverageIf(rng.Columns(1), varOutput(j, 1), rng.Columns(2)) 
     varOutput(j + 1, 1) = "" 
     End If 

    End If 
    Next 

    While Len(varOutput(j, 1)) And (j < UBound(varOutput)) 
    j = j + 1 
    Wend 

    If Len(varOutput(j, 1)) = 0 Then 
    For i = j To UBound(varOutput) 
     varOutput(i, 1) = "" 
     varOutput(i, 2) = "" 
    Next 
    End If 
    getAllAvg = varOutput 
End Function 

然後選擇一個範圍的像C2:D12和輸入:

=getAllAvg(A:B) 

並用Ctrl鍵 + 移確認 + 輸入。它會直接輸出整個列表(如果需要重新計算)

編輯

如果您的列表始終處於有序,你也可以使用此代碼:

Option Explicit 

Public Function getAllAvgSorted(rng As Range) As Variant 
    Set rng = Intersect(rng.Parent.UsedRange, rng) 

    Dim varInput As Variant 
    varInput = rng.Value 

    Dim varOutput() As Variant 
    ReDim varOutput(1 To UBound(varInput), 1 To 2) 
    varOutput(1, 1) = "" 

    Dim i As Long, j As Long 
    j = 1 

    For i = 1 To UBound(varInput) 
    If Len(varInput(i, 1)) Then 
     If varOutput(j, 1) <> varInput(i, 1) Then 
     If Len(varOutput(j, 1)) Then j = j + 1 
     varOutput(j, 1) = varInput(i, 1) 
     varOutput(j, 2) = Application.AverageIf(rng.Columns(1), varOutput(j, 1), rng.Columns(2)) 
     End If 
    End If 
    Next 

    While j < UBound(varOutput) 
    j = j + 1 
    varOutput(j, 1) = "" 
    varOutput(j, 2) = "" 
    Wend 

    getAllAvgSorted = varOutput 
End Function