VBA – 在具有相同(用户定义)function的其他单元格中复制当前单元格值

新来这里,如果我错过了一些礼节,我很抱歉。

我在Excel中写了一个VBA函数。 它似乎为当前单元正常工作,但它正在复制它的值在所有具有该function的单元格。

那就是 – 列Q中的许多单元格具有此公式= ScoreQ5()。 如果我在单元格Q2中并按F2来更新该值,则会更新Q3,Q4等,并使其等于Q2的值。 所以Q2将是正确的,但其他人可能不会。

我想也许我不应该使用ActiveCell,但我不能find任何东西,暗示它应该这样做。 有什么想法吗?

谢谢

这是函数的代码

Function ScoreQ5() Application.Volatile Dim LDoF200 As Integer Dim LDoF225 As Integer Dim HDoF204 As Integer Dim HDoF205 As Integer Dim LDoF50P As Integer Dim LDoF51P As Integer Dim HDoF50P As Integer Dim HDoF51P As Integer Dim LastRow As Integer Dim current As Long Dim question As Long Dim LDoF As Integer Dim HDoF As Integer current = 0 LDoF200 = 0 LDoF225 = 0 HDoF204 = 0 HDoF205 = 0 LDoF50P = 0 LDoF51P = 0 HDoF50P = 0 HDoF51P = 0 question = 0 LDoF = 0 HDoF = 0 LastRow = ActiveSheet.UsedRange.Rows.Count For i = 1 To LastRow If Cells(i, 2) = ActiveCell.Offset(0, -15) Then current = current + 1 If StrComp(Cells(i, 11), "5 - RedChemical_Threshold") = 0 Then question = question + 1 If Cells(i, 24) = 200 Then If StrComp(Cells(i, 9), "LDoF") = 0 Then LDoF = LDoF + 1 If Cells(i, 23) = 200 Then LDoF200 = 1 ElseIf Cells(i, 23) = 225 Then LDoF225 = 1 End If If Cells(i, 25) = 50 Then LDoF50P = 1 ElseIf Cells(i, 25) = 51 Then LDoF51P = 1 End If Else HDoF = HDoF + 1 If Cells(i, 23) = 204 Then HDoF204 = 1 ElseIf Cells(i, 23) = 205 Then HDoF205 = 1 End If If Cells(i, 25) = 50 Then HDoF50P = 1 ElseIf Cells(i, 25) = 51 Then HDoF51P = 1 End If End If Else End If Else End If Else End If Next i If ActiveCell.Offset(0, -8) = "LDoF" Then If LDoF200 + LDoF225 = 2 Then ScoreQ5 = 2 ElseIf LDoF50P + LDoF51P = 2 Then ScoreQ5 = 1 Else ScoreQ5 = 0 End If Else If HDoF204 + HDoF205 = 2 Then ScoreQ5 = 2 ElseIf HDoF50P + HDoF51P = 2 Then ScoreQ5 = 1 Else ScoreQ5 = 0 End If End If End Function 

您正在为工作表编写一个自定义用户定义函数(aka UDF)。 如果您不确定如何完成自定义函数的某些方面,请查看本机工作表函数如何处理相同的问题。

您的函数在Q列中工作(某种程度上),因为您使用Range.Offset属性硬编码的单元格范围引用。 想象一下,如果只能在列Q中使用SUM或VLOOKUP函数,会发生什么情况。他们在任何地方工作,因为您告诉他们在哪里查找带有参数的数据。 你的UDF应该以同样的方式工作。

一旦得到UDF的结果, ActiveSheet和ActiveCell属性就不会简单地“closures”。 每当您在工作簿中进行其他select时,它们都会发生变化。 这意味着您的UDF将根据新的ActiveCell属性进行重新计算,并且由于您使用Application.Volatile方法而感到愤怒。 此外,从列A:O中select任何单元格将导致错误,因为不能引用ActiveCell.Offset(0, -15)

将参数作为单元格和范围引用传递给UDF,就像使用任何本机工作表函数一样。 如果您绝对需要引用UDf所在的工作表,则您引用的任何单元格的Range.Parent属性都可以提供此function。 在捏,这可以与UDF本身的Application.Caller属性耦合。

你的叙述描述了在Q列中使用你原来的UDF,我将根据我对这个偏移列的解释。

 Function ScoreQ5(rngB As Range, rngI As Range, rngK As Range, _ rngW As Range, rngX As Range, rngY As Range, _ Optional strK As String = "5 - RedChemical_Threshold", _ Optional intX As Long = 200, _ Optional strI As String = "LDoF", _ Optional intWa As Long = 200, _ Optional intWb As Long = 225, _ Optional intWc As Long = 204, _ Optional intWd As Long = 205, _ Optional intYa As Long = 50, _ Optional intYb As Long = 51) Application.Volatile Dim LDoF200 As Integer Dim LDoF225 As Integer Dim HDoF204 As Integer Dim HDoF205 As Integer Dim LDoF50P As Integer Dim LDoF51P As Integer Dim HDoF50P As Integer Dim HDoF51P As Integer Dim current As Long Dim question As Long Dim LDoF As Integer Dim HDoF As Integer Dim i As Long current = 0 LDoF200 = 0 LDoF225 = 0 HDoF204 = 0 HDoF205 = 0 LDoF50P = 0 LDoF51P = 0 HDoF50P = 0 HDoF51P = 0 question = 0 LDoF = 0 HDoF = 0 With Application.Caller.Parent 'cut the (possible) full column ranges down to size Set rngB = Intersect(rngB, rngB.Parent.UsedRange) Set rngI = Intersect(rngI, rngI.Parent.UsedRange) Set rngK = Intersect(rngK, rngK.Parent.UsedRange) Set rngW = Intersect(rngW, rngW.Parent.UsedRange) Set rngX = Intersect(rngX, rngX.Parent.UsedRange) Set rngY = Intersect(rngY, rngY.Parent.UsedRange) For i = 1 To rngB.Rows.Count If rngB.Cells(i) = rngB.Cells(Application.Caller.Row) Then 'B current = current + 1 If StrComp(rngK.Cells(i), strK) = 0 Then 'K question = question + 1 If rngX.Cells(i) = intX Then 'X If StrComp(rngI.Cells(i), strI) = 0 Then 'I LDoF = LDoF + 1 If rngW.Cells(i) = intWa Then 'W LDoF200 = 1 ElseIf rngW.Cells(i) = intWb Then LDoF225 = 1 End If If rngY.Cells(i) = intYa Then 'Y LDoF50P = 1 ElseIf rngY.Cells(i) = intYb Then LDoF51P = 1 End If Else HDoF = HDoF + 1 If rngW.Cells(i) = intWc Then 'W HDoF204 = 1 ElseIf rngW.Cells(i) = intWd Then HDoF205 = 1 End If If rngY.Cells(i) = intYa Then 'Y HDoF50P = 1 ElseIf rngY.Cells(i) = intYb Then HDoF51P = 1 End If End If Else End If Else End If Else End If Next i End With If StrComp(rngI.Cells(i), strI) = 0 Then 'I If LDoF200 + LDoF225 = 2 Then ScoreQ5 = 2 ElseIf LDoF50P + LDoF51P = 2 Then ScoreQ5 = 1 Else ScoreQ5 = 0 End If Else If HDoF204 + HDoF205 = 2 Then ScoreQ5 = 2 ElseIf HDoF50P + HDoF51P = 2 Then ScoreQ5 = 1 Else ScoreQ5 = 0 End If End If End Function 

句法:
= ScoreQ5(B:B,I:I,K:K,W:W,X:X,Y:Y)

上述修改应该有助于您开始。 我没有样本数据,也没有预期的结果进行全面testing。 我不完全确定为什么你通过比较所收集的值为2来完成所有行的循环。 在经过所有行之后, LDoF50P + LDoF51P永远不会大于2吗? 也许,这些可能是由布尔variables而不是整型variables处理得更好。 我作为可选参数传入了一些比较常量。 它们可以按原样使用,也可以通过input附加值来修改参数。


我一直在尝试使用切割全列引用,直到UDF中Worksheet.UsedRange属性的范围。 这使您可以在工作表上实现UDF时快速使用完整的列引用,而不会由于处理大量空白单元而造成计算滞后。 tbh,我认为更多的本地工作表函数可以使用自己的单元格范围参数进行一些相同的预处理。