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