【问题标题】:excel 2007 - calculate z-scores over a range of cells in VBAexcel 2007 - 在 VBA 中计算一系列单元格的 z 分数
【发布时间】:2016-10-19 04:52:10
【问题描述】:

所以我将这个大电子表格与正常的 excel 函数放在一起,效果很好,但我想通过使用 vba 并粘贴静态值而不是降低性能的引用值来加快它并缩小文件大小(工作簿现在大约 20 mb,并将继续增长)

所以我知道我想完成什么,但我很难用简洁的表达方式表达出来,因为我的 VBA 经验仍处于起步阶段,因此我们将不胜感激。

z-score = (数字 - 所有数字的平均值) / (所有数字的标准差)

Worksheets("relay").Value("c32") 包含所有数字的平均值 Worksheets("relay").Value("c33") 包含所有数字的标准差

我想做的,是在列 worksheets("Hitterscalc").range("cb:cb") 中,用 worksheets("Hitterscalc").range( "J:J") 用于该列中其对应的 A 列单元格不等于 "" 且其对应的 AB 列等于 1 的所有行

有人对此有什么简洁的陈述吗?我可以粗略地逐个单元格地完成它,但是当我开始放入循环以遍历所有列时,它在我的代码中全部崩溃了,不幸的是在我的脑海中。

感谢您的宝贵时间

Application.ScreenUpdating = False
Worksheets("hitterscalc").Range("cb2").FormulaR1C1 = _
   "=IF(OR(RC[-79]="""",RC[-52]<>1,Settings!R4C[-74]<>""yes""),"""",(RC[-70]-relay!R32C[-77])/relay!R33C[-77])" 
Sheets("HittersCalc").Select 
Range("CB2").Select 
Selection.AutoFill Destination:=Range("CB2:CB701") Range("CB2:CB701").Select Columns("CB:CB").Select 
Selection.Copy 
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _ :=False, Transpose:=False Application.CutCopyMode = False

【问题讨论】:

  • 用公式来做这一切。一旦你有了它,然后使用宏记录器为第一行重做公式,然后让它自动填充,最后复制和粘贴值。关闭宏记录器并查看代码。它会给你一个很好的起点。您可能有兴趣使用 Range(..).End(xlDown) 计算出需要自动填充多远
  • 有没有办法进一步清理它? Application.ScreenUpdating = False Worksheets("hitterscalc").Range("cb2").FormulaR1C1 = _ "=IF(OR(RC[-79]="""",RC[-52]1,设置! R4C[-74]""yes""),"""",(RC[-70]-relay!R32C[-77])/relay!R33C[-77])" Sheets("HittersCalc") .Select Range("CB2").Select Selection.AutoFill Destination:=Range("CB2:CB701") Range("CB2:CB701").Select Columns("CB:CB").Select Selection.Copy Selection.PasteSpecial粘贴:=xlPasteValues,操作:=xlNone,SkipBlanks _ :=False,转置:=False Application.CutCopyMode = False
  • 宁可将这样的代码添加到您的答案中,也不要将其全部放在 cmets 中,否则很难阅读。这次我已经为你编辑好了。

标签: excel vba statistics


【解决方案1】:

以下内容应该等同于您的代码:

Worksheets("hitterscalc").Range("cb2").FormulaR1C1 = _
   "=IF(OR(RC[-79]="""",RC[-52]<>1,Settings!R4C[-74]<>""yes""),"""",(RC[-70]-relay!R32C[-77])/relay!R33C[-77])" 

'NOTE: Here I am assumimg that there is a column (I've gone with 
'column A but you should change it to whatever is appropriate) that has data
'as far down as you plan on autofilling the columns. So we use that to find how
'far down to autofill rather than hard coding it to 701 as in your code (this is
'the same as when you push ctrl + down in excel)
dim lastRow as int
lastRow = Sheets("HittersCalc").Range("A2").End(xlDown).row

Sheets("HittersCalc").Range("CB2").AutoFill Destination:=Range("CB2:CB" & lastRow) 

'A cleaner way to copy and paste by value that doesn't involve the clipboard
Range("CB:CB").Value = Range("CB:CB").Value

【讨论】:

    【解决方案2】:

    是的,我知道这很旧,但我最近一直在寻找类似的解决方案。我最终创建了自己的。我更喜欢可以随时随地使用的多功能功能。如果您不想计算 z 分数,那么您可以在嵌套的 IF 语句中使用该函数。

    Function zscore(i As Double, rng As Range)
    zscore = (i - Application.WorksheetFunction.Average(rng)) / Application.WorksheetFunction.stdev(rng) 
    End Function
    

    然后嵌套的 if 可能是这样的:

    =IF(COUNTA(A1)>0,IF(AB1=1,IF(C1=J1,zscore(C1,$C$1:$C$6),""),""),"")
    

    这可以随时随地为您提供 zscore,无论何时何地,您都无需进行任何计算。如果这种事情经常出现,您可以为用户扩展函数以将更多单元格传递给函数(对于 A、AB 和 J 中的值,或者他们喜欢的任何值),而不是被限制在特定的子例程中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多