从Vba中的多张收集平均值

我需要从几个工作表中计算一定范围的平均值(“C2:C11”)到一个新的工作表中。 如果添加新工作表并将数据input到指定的范围内,该function仍然可以工作。

到目前为止,我有这个

….

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 

它将一个数字返回到新表格的所需范围内,并且不准确

请帮助我了解我做错了什么。 先谢谢你。

考虑一个Collection是否是这个任务的一个好主意,让我们来看看你的代码:

一般
你可能已经这样做了,但是它在重复着
使用Option Explicit和decalre所有的variables

你的代码

 Sheets.Add 

这会将新Worksheet添加到活动Workbook ,并将其放在当前活动工作表之前,然后激活新工作表。
问题:您正在依靠默认行为来获取新的Worksheet ,您无法确定新Worksheet所在的位置,而且您没有任何参考。
build议:
获取对工作簿对象的引用,并在整个代码中使用该对象

 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 

这将从本书中的每个Worksheet中创build一个Range Collection ,包括我们刚刚创build的一个Worksheet 。 我猜你不想包括那一个。 为了便于维护,您应该创build一个variables来保存范围,并在整个代码中使用。 让我们应用以上

 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 ,然后在下一个循环覆盖它。
每次循环计算活动工作表上的一个范围的平均值(这将是刚刚添加的空白新工作表)
build议:
向前跳,看起来您想要列出新工作表上的平均值,连续行中的每张平均值一个。 因此,让我们把数组中的平均值存储在汇总表中。 请注意,如果任何一个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的最后计算值放到连续的行上

把结果放到新的表格中:把平均值收集到一个数组中,把它放到表格上

 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返回一个错误?


谈到这是否是一个好方法,应该清楚的是,已经创build了一个数组来保存结果,该数组可以通过工作簿进行填充。

像这样的东西

 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 

这个代码可能仍然有问题,这取决于您的具体要求(例如,如果“摘要”工作表已经存在,这将在平均循环中处理它)