【问题标题】:Adding an Average Calculation to the next blank row将平均计算添加到下一个空白行
【发布时间】:2021-10-09 02:25:04
【问题描述】:

我一直在努力寻找一种方法来为列中的第一个空白单元格添加平均值(该列中将有多个空白单元格,因为它被分成几组,但我希望在之后循环它它填补了第一个空白,它将为下一个空白做同样的事情。我希望它在显示的图像中平均 C2:C6,但单元格范围是动态的,列数也是如此。我试图让它找到下一个空白行然后平均高于它,但显然我不擅长代码。第二个空白是标准错误,但我希望编辑代码以将平均值应用于标准错误。此外,这段代码的大部分来自 StackExchange 上的 Ambie (Reference Link)
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

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

【问题讨论】:

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

标签: excel vba dynamic average


【解决方案1】:

我设计了下面的代码是为了方便您理解,因为您将不得不在很长时间内对其进行修改。

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),这是第一个数字列下方的第一个空白单元格。 它以相同的方式计算要平均的范围,除了它使用最后使用的单元格而不是下一个空白单元格。现在工作表函数用于计算平均值和标准差,将第一个写入Target,第二个写入Target下方的单元格。

要理解的重要一点是工作表是在Sub MeanSEM01 中定义的。 FirstDataCell 取自该工作表。 Sub CalculateAvgFirstDataCell 知道 Target 的工作表。因此,只需更改MeanSEM01 中的选项卡名称,即可将整个操作转移到另一个工作表。同样,可以在此处更改列: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

【讨论】:

  • 我想通了!我不得不将没有数字数据的列从中间移到前面:)
  • 我使用Function StdErr(Rng As Range) As Double Dim StDev As Double Dim Size As Integer StDev = WorksheetFunction.StDev_S(Rng) Size = WorksheetFunction.Count(Rng) StdErr = StDev / Sqr(Size) End Function 将 StDev 替换为 StdErr 但现在我想在不包括上述组数据或 SE 的情况下计算下一组均值和 SE 的问题。我将如何实现自动化?在上面的示例图像中,我有一个参考图像,它大致显示了双空格之间的分组情况
  • 这里的大多数人都不喜欢做后续问题,而我就是其中之一。最好的方法是提出一个新问题。这就是您有空间解释您的需求和更广泛的受众为您提供最佳答案的地方。
猜你喜欢
  • 1970-01-01
  • 2015-01-13
  • 2014-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-29
相关资源
最近更新 更多