【问题标题】:VBA: how to create a new array showing the calculated averages for each column in another array?VBA:如何创建一个新数组,显示另一个数组中每一列的计算平均值?
【发布时间】:2021-02-10 12:45:07
【问题描述】:

我是 VBA 和 Stack Overflow 的新手,对任何笨拙表示歉意。

根据下面的代码,我生成 Array1 的随机值,其大小由用户通过输入框指定。然后将 Array1 输出到工作表以进行测试。出于速度原因,我正在尽量减少与工作表的交互。

问题:如何计算 Array1 的每一列的平均值(这些平均值输入到要创建的 Array2 中,测量 1 行和与 Array1 中的列数相同的宽度)?计算严格在内存中完成,而不是在工作表中。每列分别取平均值。然后将这些 Array2 结果粘贴到工作表中粘贴 Array1 的位置下方的第二个空行中? (您会看到 Array1 粘贴从单元格 A1 开始并从那里向下/向右扩散)。

我已经研究并尝试过,但没有成功。运行以下代码的简单输入(对我来说很好)是 10 行,2 列,alpha = 1,beta = 1

Sub MC()

'   Clear contents of active worksheet
    Cells.Clear

'   Moves cursor to starting point
    Range("A1").Select

'   Declarations of variables and arrays
    Dim CellsDown As Long, CellsAcross As Long
    Dim Alpha As Double, Beta As Double
    Dim i As Long, j As Integer
    Dim StartTime As Double
    Dim Array1() As Double
    Dim OutputSim As Range
     
'   Set array dimensions and other inputs for running Monte Carlo
    CellsDown = InputBox("How many rows?")
        If CellsDown = 0 Then Exit Sub
    CellsAcross = InputBox("How many columns?")
        If CellsAcross = 0 Then Exit Sub
    Alpha = InputBox("Distribution shape alpha value?")
        If Alpha <= 0 Then Exit Sub
    Beta = InputBox("Distribution shape beta value?")
        If Beta <= 0 Then Exit Sub
    
'   Record starting time
    StartTime = Timer
     
'   Redimension array
    ReDim Array1(1 To CellsDown, 1 To CellsAcross)
   
'   Set worksheet range
    Set OutputSim = ActiveCell.Range(Cells(1, 1), Cells(CellsDown, CellsAcross))
  
'   Fill array1 with random values generated from inverse of cumulative beta probability density function
    Application.ScreenUpdating = False
    
    For i = 1 To CellsDown
        For j = 1 To CellsAcross
            Randomize
            Array1(i, j) = Application.Beta_Inv(Application.RandBetween(0.0000001, 100 - 0.0000001) / 100, Alpha, Beta, 0, 1)
        Next j
    Next i

'   Transfer array1 to worksheet
    OutputSim.Value = Array1
  
'   Display elapsed time
    Application.ScreenUpdating = True
    MsgBox Format(Timer - StartTime, "00.00") & " seconds"
 
End Sub

【问题讨论】:

    标签: arrays excel vba average


    【解决方案1】:

    请在Array1加载循环之后插入下一段代码:

    'Fill the average array:____________________________________________________________________
     Dim arrAv, arrCol
     
     ReDim arrAv(CellsAcross - 1)       '1D array to keep the columns average
     For i = 0 To UBound(Array1, 2) - 1 'iterate between the array columns
        arrCol = Application.index(Array1, 0, i + 1) 'obtain a column slice from Array1
        arrAv(i) = WorksheetFunction.Average(arrCol) 'fill the array element with the Average
     Next i
     'drop the array content at two columns to the right of OutputSim:
     OutputSim.Offset(0, 2 + OutputSim.Columns.count).Resize(1, UBound(arrAv) + 1).Value = arrAv
    '____________________________________________________________________________________________
    

    【讨论】:

    • 非常感谢!一个完美而直接的解决方案。根据我上面的原始问题,只有很小的区别我试图将新的 Array2 平均 2 行放置在粘贴到工作表中的 Array1 的最后一行下方,并且您的解决方案将 Array2 平均 2 列放置在粘贴的 Array1 的右侧.这比我最初的尝试要好得多,它更具可读性,感谢您改进!
    • @Lil' Lou - user9788072:很高兴我能帮上忙!我虽然我设计代码的方式更好,但是如果你需要放在你要求的地方,最后的代码行可以转换为OutputSim.Offset(1 + OutputSim.Rows.count, 0).Resize(1, UBound(arrAv) + 1).Value = arrAv...
    猜你喜欢
    • 1970-01-01
    • 2021-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-16
    • 2022-10-14
    • 2017-05-06
    • 1970-01-01
    相关资源
    最近更新 更多