将平均计算添加到下一个空白行

Adding an Average Calculation to the next blank row

我一直在努力寻找一种方法来为列中的第一个空白单元格添加平均值(列中会有多个空白单元格,因为它被分成几组,但我希望只是循环它所以在它填满第一个空白后,它会为下一个空白做同样的事情。我希望它在显示的图像中平均 C2:C6 但单元格范围和列数一样是动态的。我试图让它找到下一个空白行然后平均高于它,但显然我不擅长代码。第二个空白是标准错误,但我希望编辑代码以应用于标准错误。此外,这段代码的大部分是来自 StackExchange 上的 Ambie ()
Example of the sheet I am working with

Sub MeanSEM01()


Dim nextrow As Long
nextrow = Cells(Rows.Count, "A").End(xlUp).Row + 1

Dim lastCol As Long, i As Long
Dim rng As Range

'Find the last column.
'Assumes the relevant column is the last one with data in row 5.
With Sheet1
    lastCol = .Cells(nextrow - 1, .Columns.Count).End(xlToLeft).Column
End With

'Iterate the columns from 1 (ie "A") to the last.
For i = 1 To lastCol
    With ActiveSheet
        'Define the data range for this column.
        'Assumes last cell from bottom of sheet is the end of data.
        Set rng = .Range(.Cells(nextrow - 1, i), .Cells(.Rows.Count, i).End(xlUp))
        'Write the average to the cell above.
        .Cells(nextrow, i) = WorksheetFunction.Average(rng)
    End With
Next

End Sub

我还检查了即时 Window,发现我的范围定义肯定是错误的,这就是它在平均步骤失败的原因。我也尝试从工作表函数更改为公式 Range(.Cells(nextrow, i)).Formula = "=Average(rng)" 但我认为我的范围是我的问题。

为了方便大家理解,我设计了下面的代码,因为过不了多久就要修改了。

Option Explicit

Sub MeanSEM01()
    ' 306

    Dim Ws          As Worksheet        ' define the sheet to work on
    Dim Rng         As Range            ' range of relevant column headers
    Dim C           As Long             ' loop counter: columns of Rng
    
    Set Ws = Worksheets("Sheet1")       ' adapt the name to what you have
    With Ws
        ' in row 1, start from column C to last used cell in row 1
        ' change to suit
        Set Rng = .Range(.Cells(1, "C"), .Cells(1, .Columns.Count).End(xlToLeft))
    End With
    
    For C = 1 To Rng.Columns.Count
        CalculateAvg Rng.Columns(C).Offset(1)
    Next C
End Sub

Private Sub CalculateAvg(FirstDataCell As Range)
    ' 306
    
    Dim Rng         As Range        ' Data range
    Dim Target      As Range        ' Cell to write data to

    Set Target = FirstDataCell.End(xlDown).Offset(1)
    With FirstDataCell.Worksheet
        Set Rng = .Range(FirstDataCell, FirstDataCell.End(xlDown))
        Target.Value = WorksheetFunction.Average(Rng)
        Target.Offset(1).Value = WorksheetFunction.StDev(Rng)
    End With
End Sub

Option Explicit 开始。你需要它,因为你认为你不需要。

'Sub MeanSEM01' 不是一个好名字,因为它需要先验知识才能理解。名字应该是描述性的,而不是谜语。此过程只是找出您有多少列。它通过查看第一行来做到这一点。然后它只为每列调用一次 Sub CalculateAvg 。每次它传递该列的单元格,但从第 1 行下方的行(那将是第 2 行,对吗?)到 Sub CalculateAvg 作为参数。 Sub CalculateAvg 理解这是范围内第一个要取平均值的单元格。

Sub CalculateAvg 使用第一个单元格找到要写入的单元格 (Target),这是第一个数字列下方的第一个空白单元格。 它以相同的方式计算要平均的范围,除了它使用最后使用的单元格而不是下一个空白单元格。现在 worksheet 函数用于计算平均值和标准偏差,将第一个写入 Target,将第二个写入 Target.

下面的单元格

需要理解的重要一点是作品sheet 是在Sub MeanSEM01 中定义的。 FirstDataCell 取自该作品sheet。 Sub CalculateAvgFirstDataCell 知道 Target 的 sheet。因此,只需更改 MeanSEM01 中的选项卡名称,即可将整个操作转移到另一个 sheet 中。同样,可以在此处更改列:Set Rng = .Range(.Cells(1, "C"), .Cells(1, .Columns.Count).End(xlToLeft)) 和这一行中的 FirstDataCell CalculateAvg Rng.Columns(C).Offset(1).

到运行代码只需调用MeanSEM01。您将永远不需要调用 Sub CalculateAvg。它仅供 Sub MeanSEM01 使用,这就是为什么它被定义为 Private.