2012-10-21 157 views
1

我需要從幾個工作表中計算一定範圍(「C2:C11」)的平均值到新的工作表中。如果添加新工作表並將數據輸入到指定的範圍內,該功能仍然可以工作。從Vba中的多個工作表中收集平均值

到目前爲止,我有這個

....

Sheets.Add 

Dim myavg As Collection 
Set myavg = New Collection 

For Each wsheet In Worksheets 
    myavg.Add wsheet.Range("B2:B11") 
Next  
For i = 1 To myavg.Count 
    avg1 = Application.WorksheetFunction.Average(Range("B2:B11")) 
Next 

curColumn = 5 
curRow = 4 

For i = 1 To myavg.Count 
    ActiveSheet.Cells(curRow, curColumn).Value = avg1 
    curRow = curRow + 1 
Next 

...

它返回一個數字到新表的所需範圍和它的不準確

請幫我理解我做錯了什麼。 預先感謝您。

+2

有這個代碼中的很多矯枉過正。你絕對不*需要使用一個集合來實現這一點。只需在'Worksheets'中使用'for each',計算平均值並將其輸出到適當的單元格中,而不是使用3(!!)for循環。 – ApplePie

+0

至於準確性問題,「avg1」的數據類型是什麼? – ApplePie

回答

0

暫且不論是否不Collection是這個任務是一個好主意,讓你的代碼:

一般
您可能已經做到了這一點,但它warrents重複
使用Option Explicit和decalre所有變量

代碼

Sheets.Add 

這會將新的Worksheet添加到活動的Workbook,並將其放在當前活動工作表之前,然後激活新工作表。
問題: 您正在依靠默認行爲獲取新的Worksheet,您無法確定新工作表的位置,並且您沒有提及它。
建議:
獲取到工作簿對象的引用和使用整個代碼

Dim wb As Workbook 
Set wb = ActiveWorkbook 

控制什麼,在哪裏以及如何添加到工作簿

Dim wsSummary as Worksheet 
Set wsSummary = wb.Worksheets.Add(After:=wb.Worksheets(wb.Worksheets.Count)) 
wsSummary.Name = "Summary" 

您的代碼

For Each wsheet In Worksheets 
    myavg.Add wsheet.Range("B2:B11") 
Next 

這產生於RangeCollection其次,每本書Worksheet包括我們剛剛創建的。我猜你不想包括那一個。爲了便於維護,您應該創建一個變量來保存範圍並在整個代碼中使用它。 讓應用上述

Dim wsheet as WorkSheet 
Dim RangeAddress As String 
RangeAddress = "B2:B11" 
For Each wsheet In wb.Worksheets 
    If wsheet.name <> wsSummary.Name Then 
     myavg.Add wsheet.Range(RangeAddress) 
    End If 
Next 

代碼

For i = 1 To myavg.Count 
    avg1 = Application.WorksheetFunction.Average(Range("B2:B11")) 
Next 

問題: 您遍歷Collection但在循環不引用它。每次通過計算avg1,然後在下一個循環中覆蓋它。
通過你計算活動工作表範圍的平均值(這將是剛加入的新的空白表)
建議每一次循環中:
跳躍前進,它看起來像你想上列出的平均值新的紙張,每張紙在連續的行上。所以讓我們把數組中的平均值存儲在彙總表中。請注意,如果Range中的任何一個爲空,則Average將導致錯誤。

Dim avg() as Variant 
Redim avg(1 to myavg.Count, 1 To 1) 
For i = 1 To myavg.Count 
    avg(i, 1) = Application.WorksheetFunction.Average(myavg(i)) 
Next 

代碼

curColumn = 5 
curRow = 4 

For i = 1 To myavg.Count 
    ActiveSheet.Cells(curRow, curColumn).Value = avg1 
    curRow = curRow + 1 
Next 

問題:
這段代碼僅僅把的avg1最後計算的值在連續的行

把結果放在新表:有colle反恐執行局的平均值成陣列,讓端起到紙張

Dim curColumn as Long, curRow As Long 
curColumn = 5 
curRow = 4 

wsSummary.Cells(curRow, curColumn).Resize(UBound(avg, 1), 1) = avg 

請告訴我不與衣食住行到目前爲止是Error Handling。代碼可能出錯的方法很多,所以在代碼中包含Error Handling是明智的。例如,如果已經有一張名爲「摘要」的工作表?如果Average返回錯誤怎麼辦?


轉到這是否是一個很好的方法,但是應該清楚的是,在創建了一個數組來保存的結果,即陣列可以在穿過工作簿來填充。

像這樣的事情

Sub Demo() 
    Dim wb As Workbook 
    Set wb = ActiveWorkbook 

    Dim RangeAddress As String 
    RangeAddress = "B2:B11" 

    Dim wsSummary As Worksheet 

    Dim avg() As Variant 
    ReDim avg(1 To wb.Worksheets.Count, 1 To 1) 
    For i = 1 To UBound(avg, 1) 
     With wb.Worksheets(i).Range(RangeAddress) 
      If WorksheetFunction.Count(.Value) > 0 Then 
       avg(i, 1) = WorksheetFunction.Average(.Value) 
      Else 
       avg(i, 1) = "No Values On Sheet" 
      End If 
     End With 
    Next 

    Dim curColumn As Long, curRow As Long 
    curColumn = 5 
    curRow = 4 

    On Error Resume Next 
    wsSummary = wb.Worksheets("Summary") 
    If Err.Number <> 0 Then 
     ' Summary sheet does not exist, create it 
     Err.Clear 
     On Error GoTo 0 
     Set wsSummary = wb.Worksheets.Add(After:=wb.Worksheets(wb.Worksheets.Count)) 
     wsSummary.Name = "Summary" 
    Else 
     On Error GoTo 0 
     ' Summary sheet already exists 
     ' what do you wnat to do? 
    End If 

    wsSummary.Cells(curRow, curColumn).Resize(UBound(avg, 1), 1) = avg 

End Sub 

此代碼可能還是有問題,根據您的具體要求(例如,如果「摘要」表已經存在,這將在平均循環處理它)

+0

哇。非常感謝。我非常感謝您花時間瞭解我的問題並解釋我的錯誤。經過一些修改後,我得到它完美運行。我學到了很多,再次感謝:) – MyCatTiger