【问题标题】:UDF to return Y value from given X value using 5th Polynomial使用第五多项式从给定 X 值返回 Y 值的 UDF
【发布时间】:2020-07-26 15:31:56
【问题描述】:

我在同一个工作簿的多个工作表上有一个范围,一列中有 35 个“X”值,需要返回与名为“DB”的固定工作表上的自定义第五多项式曲线/函数相对应的“Y”值对于上述曲线,支持 C37:C76 上的“x”值和 D37:D76 上的“y”值。

本质上是一个图形化的 VLOOKUP 函数,而不是一个包含 1000 行的表。

作为一次性计算,常规计算方法 100% 有效,但如果您需要为多个工作表上的多个 X 值计算 Y,这将成为一个问题。我认为UDF会起作用,但我不知道如何实际做到这一点。我尝试了一些代码变体并将其清理为这篇文章的起点。

任何帮助使这个 UDF 工作将不胜感激。

Function ADJ(X As Single) As Single

'X = FUNCTION INPUT VALUE
'Y = RESULT = ADJ = C5*X^5 + C4*X^4 + C3*X^3 + C2*X^2 + C1*X^1 + A
        
        C1 = Sheets(11).Evaluate("=INDEX(LINEST(R37C3:R76C3, R37C4:R76C4^{1,2,3,4,5}), 1, 5)")
        C2 = Sheets(11).Evaluate("=INDEX(LINEST(R37C3:R76C3, R37C4:R76C4^{1,2,3,4,5}), 1, 4)")
        C3 = Sheets(11).Evaluate("=INDEX(LINEST(R37C3:R76C3, R37C4:R76C4^{1,2,3,4,5}), 1, 3)")
        C4 = Sheets(11).Evaluate("=INDEX(LINEST(R37C3:R76C3, R37C4:R76C4^{1,2,3,4,5}), 1, 2)")
        C5 = Sheets(11).Evaluate("=INDEX(LINEST(R37C3:R76C3, R37C4:R76C4^{1,2,3,4,5}), 1, 1)")
         A = Sheets(11).Evaluate("=INDEX(LINEST(R37C3:R76C3, R37C4:R76C4^{1,2,3,4,5}), 1, 6)")
       ADJ = C5 * X ^ 5 + C4 * X ^ 4 + C3 * X ^ 3 + C2 * X ^ 2 + C1 * X ^ 1 + A
         
End Function

作为一个子运行它:

Option Explicit

Sub ADJ1()

Dim ADJ As Variant
Dim X As Variant
Dim A As Variant
Dim C1 As Variant
Dim C2 As Variant
Dim C3 As Variant
Dim C4 As Variant
Dim C5 As Variant

X = 3

         C1 = Sheets(11).Evaluate("=INDEX(LINEST(D37:D76, C37:C76^{1,2,3,4,5}), 1, 5)")
         C2 = Sheets(11).Evaluate("=INDEX(LINEST(D37:D76, C37:C76^{1,2,3,4,5}), 1, 4)")
         C3 = Sheets(11).Evaluate("=INDEX(LINEST(D37:D76, C37:C76^{1,2,3,4,5}), 1, 3)")
         C4 = Sheets(11).Evaluate("=INDEX(LINEST(D37:D76, C37:C76^{1,2,3,4,5}), 1, 2)")
         C5 = Sheets(11).Evaluate("=INDEX(LINEST(D37:D76, C37:C76^{1,2,3,4,5}), 1, 1)")
          A = Sheets(11).Evaluate("=INDEX(LINEST(D37:D76, C37:C76^{1,2,3,4,5}), 1, 6)")
       
       'ADJ = C5 * X ^ 5 + C4 * X ^ 4 + C3 * X ^ 3 + C2 * X ^ 2 + C1 * X ^ 1 + A
       
       ADJ = X ^ 5 + X ^ 4 + X ^ 3 + X ^ 2 + X ^ 1
       MsgBox ADJ
       
       
End Sub

【问题讨论】:

  • 如果要计算工作表公式,则需要使用Worksheet.Evaluate 方法。例如C1 = mySheet.Evaluate("=INDEX(LINEST(R37C3:R76C3, R37C4:R76C4^{1,2,3,4,5}), 1, 5)") 并将ADJ = ... 行移至该行的输入分配后。
  • 谢谢蒂姆,我更新了代码(如上所示),但得到了#Value!错误
  • 从 Sub 运行你的函数,这样你就可以看到问题出在哪里。你真的有一个代号为“mySheet”的工作表吗?
  • 我给 X 一个随机值,并且没有任何 C1 到 A 值,它可以工作,即弹出一个消息框,其中包含计算的 ADJ 值。例如,只要我添加 A,我就会收到类型不匹配错误。我猜这意味着 A 计算返回错误..也许?难道是Sheets(11).Evaluate("=INDEX(LINEST(D37:D76, C37:C76^{1,2,3,4,5}), 1, 6)")格式不对?

标签: excel vba user-defined-functions polynomials


【解决方案1】:

我有一个解决方案和意见。我仍然不确定这个意见是否完全正确。 意见:我永远不会参考范围使用 UDF。您正在使用的 Range 必须是函数的参数。 请参阅此解决方案:

Public Function ADJ(X As Range, Y As Range, xvalue As Double) As Double
    Dim pol As Variant
    Dim arrPolNth As Variant
    Dim n As Integer
    n = 5
    arrPolNth = Array(1, 2, 3, 4, 5)
    pol = Application.LinEst(Y, Application.Power(X, arrPolNth))
    Dim i As Integer
    For i = LBound(pol) To UBound(pol)
        ADJ = ADJ + Application.Power(xvalue, n - i + 1) * pol(i)
    Next i
End Function

这不是最好的,因为多项式的阶也应该是一个参数。

【讨论】:

  • 谢谢维克多。有趣的解决方案。我想到了使用 Range,因为这样我就可以绘制曲线并对其进行微调以适应一个中心位置。如果我理解正确,那么该范围应该是 VBA 代码的一部分,而不是位于工作表上?如果是这样,我将在哪里定义 X 和 Y 的值(每个 40 个值)?
  • 实际上,如果您的函数是从工作表中调用的,那么与范围对象直接通信并不是一个好习惯。如果您想要一个数组(范围)而不是单个值,该函数应该有一个输入范围,并且可以返回计算出的估计值的数组。如果您对此解决方案感到满意,我可以为您修改代码。
  • 啊,现在我知道你在那里做了什么。我错过了在 UDF 中定义范围的事实,即=ADJ(D37:D76,C37:C76,H51)(即使你这么说)现在它就像你上面建议的那样完美地工作!非常感谢维克多!
猜你喜欢
  • 2020-12-06
  • 2013-04-22
  • 1970-01-01
  • 1970-01-01
  • 2021-04-01
  • 2018-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多