如何动态计算多个过滤数据表的平均值 - VBA
how to calculate average for multiple tables of filtered data dynamically - VBA
我有一个 table,我需要在其中找到不同样本中存在的元素。
对于每个样本,迭代次数都是一个变量——我可以有两行样本 1 和 3 行样本 2 或 5 行样本 4。作为元素的列数也可以不同。在这种情况下,我考虑了 3 个样本和 17 个元素。
我需要根据样本进行过滤。比如样本 1。然后需要计算样本 1 的所有条目的平均值。然后在该样本 2 的下方显示值,并计算样本 2 的所有条目的平均值。
我是 vba 的初学者,因此我使用的代码无法针对动态值范围执行此操作。另外,我只能使用宏记录器计算平均值。我不知道如何将这两个代码合二为一。我试着搜索了很多关于这个主题的内容
我也包含了我的代码。
任何帮助将非常感激!!!谢谢
Sub sorttable()
Dim j As Long 'row variable
On Error GoTo Err_Execute
Dim i As Long
'Start search in row 1 in sheet1
j = 1
'Column counter for sheet2
i = 1
While Len(Range("A" & CStr(j)).Value) > 0
If Range("A" & CStr(j)).Value = "Sample1" Then
Range(Range("A" & CStr(j)), Range("A" & CStr(j)).End(xlToRight)).Select
Selection.Copy
Sheets("Sheet2").Select
Sheet2.Cells(i, 1).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
'Cells(j + 1, 1) = "=AVERAGE(A1:C" & j - 1 & ")" 'used to calculate avg
i = i + 1
Sheets("Sheet1").Select
ElseIf Range("A" & CStr(j)).Value = "Sample2" Then
Range(Range("A" & CStr(j)), Range("A" & CStr(j)).End(xlToRight)).Select
Selection.Copy
Sheets("Sheet2").Select
Sheet2.Cells(i, 1).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
i = i + 1
Sheets("Sheet1").Select
ElseIf Range("A" & CStr(j)).Value = "Sample3" Then
Range(Range("A" & CStr(j)), Range("A" & CStr(j)).End(xlToRight)).Select
Selection.Copy
Sheets("Sheet2").Select
Sheet2.Cells(i, 1).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
i = i + 1
Sheets("Sheet1").Select
End If
j = j + 1
Wend
Application.CutCopyMode = False
MsgBox "the values have been extracted"
Exit Sub
Err_Execute:
MsgBox "Error Occured"
End Sub
'code- part of it for calculating the average
Application.CutCopyMode = False
Selection.AutoFill Destination:=Range("A9:B9"), Type:=xlFillDefault
Range("A9:B9").Select
Range("B9").Select
Selection.ClearContents
ActiveCell.FormulaR1C1 = "= AVERAGE(R[-2]C,R[-1]C)"
Range("B9").Select
Selection.AutoFill Destination:=Range("B9:R9"), Type:=xlFillDefault
Range("B9:R9").Select
Range("A11").Select
Sheets("Sheet2").Select
Range("A27").Select
Sheets("Sheet1").Select
Range("A8:R10").Select
Selection.Copy
Sheets("Sheet2").Select
Range("A11").Select
ActiveSheet.Paste
Range("A14").Select
Application.CutCopyMode = False
Selection.Style = "Normal 2"
ActiveCell.FormulaR1C1 = "Average"
Range("B14").Select
ActiveCell.FormulaR1C1 = "= AVERAGE(R[-3]C:R[-1]C)"
Range("B14").Select
Selection.AutoFill Destination:=Range("B14:R14"), Type:=xlFillDefault
Range("B14:R14").Select
Range("A16").Select
End Sub
看起来您一开始就录制了宏,然后尝试从那里修改它。这是一个很好的第一步,所以现在有一些事情需要注意:
- 宏录制器捕获了很多很多不需要的东西,所以不要使用
Select
或Activate
。
- 由于每个样本组的数据可能不同,因此您的代码必须考虑到这一点。查看下面的示例代码并注意它循环计算示例组中有多少行,然后动态填充该组列的公式。
Option Explicit
Sub SortTable()
Dim ws As Worksheet
Set ws = ActiveSheet
Dim numSampleRows As Long
numSampleRows = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row - 1
Dim sampleRow As Range
Set sampleRow = ws.Range("A2")
Dim i As Long
Dim numSamplesInGroup As Long
Dim currentSampleLabel As String
Dim numSampleColumns As Long
Dim avgRow As Long
Dim avgCol As Long
For i = 1 To (numSampleRows + 1)
'--- look at the sample labels to determine how
' many are in this group
If numSamplesInGroup = 0 Then
'--- this is the start of a sample group
currentSampleLabel = sampleRow.Offset(0, 0)
numSamplesInGroup = 1
ElseIf currentSampleLabel = sampleRow.Offset(0, 0) Then
'--- continue to count the samples in the group
numSamplesInGroup = numSamplesInGroup + 1
Else
'--- we've reached the end of the sample group
' so insert two empty rows here
sampleRow.EntireRow.Insert
sampleRow.EntireRow.Insert
Debug.Print sampleRow.Address
'--- create the AVERAGE formula for each populated column
' ASSUMES all the columns are consistent for each sample group
avgRow = sampleRow.Offset(-2, 0).Row
ws.Cells(avgRow, 1) = "Average"
numSampleColumns = ws.Cells(avgRow - 1, ws.Columns.Count).End(xlToLeft).Column
For avgCol = 1 To (numSampleColumns - 1)
sampleRow.Offset(-2, avgCol).FormulaR1C1 = _
"=AVERAGE(R" & _
avgRow - numSamplesInGroup & _
"C" & avgCol + 1 & _
":R" & avgRow - 1 & "C" & avgCol + 1 & ")"
Next avgCol
'--- reset for the next loop
currentSampleLabel = sampleRow.Offset(0, 0)
numSamplesInGroup = 0
End If
'--- move down one row
Set sampleRow = sampleRow.Offset(1, 0)
Next i
End Sub
我有一个 table,我需要在其中找到不同样本中存在的元素。 对于每个样本,迭代次数都是一个变量——我可以有两行样本 1 和 3 行样本 2 或 5 行样本 4。作为元素的列数也可以不同。在这种情况下,我考虑了 3 个样本和 17 个元素。 我需要根据样本进行过滤。比如样本 1。然后需要计算样本 1 的所有条目的平均值。然后在该样本 2 的下方显示值,并计算样本 2 的所有条目的平均值。
我是 vba 的初学者,因此我使用的代码无法针对动态值范围执行此操作。另外,我只能使用宏记录器计算平均值。我不知道如何将这两个代码合二为一。我试着搜索了很多关于这个主题的内容
我也包含了我的代码。 任何帮助将非常感激!!!谢谢
Sub sorttable()
Dim j As Long 'row variable
On Error GoTo Err_Execute
Dim i As Long
'Start search in row 1 in sheet1
j = 1
'Column counter for sheet2
i = 1
While Len(Range("A" & CStr(j)).Value) > 0
If Range("A" & CStr(j)).Value = "Sample1" Then
Range(Range("A" & CStr(j)), Range("A" & CStr(j)).End(xlToRight)).Select
Selection.Copy
Sheets("Sheet2").Select
Sheet2.Cells(i, 1).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
'Cells(j + 1, 1) = "=AVERAGE(A1:C" & j - 1 & ")" 'used to calculate avg
i = i + 1
Sheets("Sheet1").Select
ElseIf Range("A" & CStr(j)).Value = "Sample2" Then
Range(Range("A" & CStr(j)), Range("A" & CStr(j)).End(xlToRight)).Select
Selection.Copy
Sheets("Sheet2").Select
Sheet2.Cells(i, 1).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
i = i + 1
Sheets("Sheet1").Select
ElseIf Range("A" & CStr(j)).Value = "Sample3" Then
Range(Range("A" & CStr(j)), Range("A" & CStr(j)).End(xlToRight)).Select
Selection.Copy
Sheets("Sheet2").Select
Sheet2.Cells(i, 1).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
i = i + 1
Sheets("Sheet1").Select
End If
j = j + 1
Wend
Application.CutCopyMode = False
MsgBox "the values have been extracted"
Exit Sub
Err_Execute:
MsgBox "Error Occured"
End Sub
'code- part of it for calculating the average
Application.CutCopyMode = False
Selection.AutoFill Destination:=Range("A9:B9"), Type:=xlFillDefault
Range("A9:B9").Select
Range("B9").Select
Selection.ClearContents
ActiveCell.FormulaR1C1 = "= AVERAGE(R[-2]C,R[-1]C)"
Range("B9").Select
Selection.AutoFill Destination:=Range("B9:R9"), Type:=xlFillDefault
Range("B9:R9").Select
Range("A11").Select
Sheets("Sheet2").Select
Range("A27").Select
Sheets("Sheet1").Select
Range("A8:R10").Select
Selection.Copy
Sheets("Sheet2").Select
Range("A11").Select
ActiveSheet.Paste
Range("A14").Select
Application.CutCopyMode = False
Selection.Style = "Normal 2"
ActiveCell.FormulaR1C1 = "Average"
Range("B14").Select
ActiveCell.FormulaR1C1 = "= AVERAGE(R[-3]C:R[-1]C)"
Range("B14").Select
Selection.AutoFill Destination:=Range("B14:R14"), Type:=xlFillDefault
Range("B14:R14").Select
Range("A16").Select
End Sub
看起来您一开始就录制了宏,然后尝试从那里修改它。这是一个很好的第一步,所以现在有一些事情需要注意:
- 宏录制器捕获了很多很多不需要的东西,所以不要使用
Select
或Activate
。 - 由于每个样本组的数据可能不同,因此您的代码必须考虑到这一点。查看下面的示例代码并注意它循环计算示例组中有多少行,然后动态填充该组列的公式。
Option Explicit
Sub SortTable()
Dim ws As Worksheet
Set ws = ActiveSheet
Dim numSampleRows As Long
numSampleRows = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row - 1
Dim sampleRow As Range
Set sampleRow = ws.Range("A2")
Dim i As Long
Dim numSamplesInGroup As Long
Dim currentSampleLabel As String
Dim numSampleColumns As Long
Dim avgRow As Long
Dim avgCol As Long
For i = 1 To (numSampleRows + 1)
'--- look at the sample labels to determine how
' many are in this group
If numSamplesInGroup = 0 Then
'--- this is the start of a sample group
currentSampleLabel = sampleRow.Offset(0, 0)
numSamplesInGroup = 1
ElseIf currentSampleLabel = sampleRow.Offset(0, 0) Then
'--- continue to count the samples in the group
numSamplesInGroup = numSamplesInGroup + 1
Else
'--- we've reached the end of the sample group
' so insert two empty rows here
sampleRow.EntireRow.Insert
sampleRow.EntireRow.Insert
Debug.Print sampleRow.Address
'--- create the AVERAGE formula for each populated column
' ASSUMES all the columns are consistent for each sample group
avgRow = sampleRow.Offset(-2, 0).Row
ws.Cells(avgRow, 1) = "Average"
numSampleColumns = ws.Cells(avgRow - 1, ws.Columns.Count).End(xlToLeft).Column
For avgCol = 1 To (numSampleColumns - 1)
sampleRow.Offset(-2, avgCol).FormulaR1C1 = _
"=AVERAGE(R" & _
avgRow - numSamplesInGroup & _
"C" & avgCol + 1 & _
":R" & avgRow - 1 & "C" & avgCol + 1 & ")"
Next avgCol
'--- reset for the next loop
currentSampleLabel = sampleRow.Offset(0, 0)
numSamplesInGroup = 0
End If
'--- move down one row
Set sampleRow = sampleRow.Offset(1, 0)
Next i
End Sub