【问题标题】:Complex Nested IF AND Formula Being Written to Sheet by VBAVBA 将复杂的嵌套 IF AND 公式写入工作表
【发布时间】:2018-10-30 23:12:13
【问题描述】:

我目前有一个复杂的公式,我正试图通过 VBA 将其放入单元格中。当前的工作公式(在单元格BP2中)如下:

'=IF(X2="No Bonus",1,
'IF(AND(((AG2-AF2+1)/(365/12))>=50,AD2="N"),5,
'IF(AND(((AG2-AF2+1)/(365/12))>=40,AD2="N"),4,
'IF(AND(((AG2-AF2+1)/(365/12))>=30,AD2="N"),2,
'IF(AND(((AG2-AF2+1)/(365/12))>=20,AD2="N"),1,
'IF(AND(((AG2-AF2+1)/(365/12))>0,AD2="N"),0.5,
'IF(AND(((AG2-AF2+1)/(365/12))>=20,AD2="Y"),1,
'IF(AND(((AG2-AF2+1)/(365/12))>=15,AD2="Y"),2,
'IF(AND(((AG2-AF2+1)/(365/12))>=0,AD2="Y"),0.3,0)))))))))

我将代码放置在 BP 列中现有数据下方的可变范围内。我的代码目前如下:

Dim LastRowExisting As Long
Dim LastRowNew As Long

LastRowExisting = Worksheets("MyWorksheet").Range("CE1").Value 'LastRow of Existing data stored here by macro earlier
LastRowNew = Worksheets("MyWorksheet").Range("A" & rows.Count).End(xlUp).Row 'requires Column A "Source" is always populated on all lines    

Worksheets("MyWorksheet").Range("BP" & LastRowExisting + 1 & ":" & "BP" & LastRowNew).FormulaR1C1 = "=IF(RC[-44]=""No Bonus"",""1"", _
IF(AND(((RC[-35]-RC[-36]+1)/(365/12))>=50,RC[-38]=""N"",""5"", _
IF(AND(((RC[-35]-RC[-36]+1)/(365/12))>=40,RC[-38]=""N"",""4"", _
IF(AND(((RC[-35]-RC[-36]+1)/(365/12))>=30,RC[-38]=""N"",""2"", _
IF(AND(((RC[-35]-RC[-36]+1)/(365/12))>=20,RC[-18]=""N"",""1"", _
IF(AND(((RC[-35]-RC[-36]+1)/(365/12))>=0,RC[-38]=""N"",""0.5"", _
IF(AND(((RC[-35]-RC[-36]+1)/(365/12))>=20,RC[-38]=""Y"",""1"", _
IF(AND(((RC[-35]-RC[-36]+1)/(365/12))>=15,RC[-38]=""Y"",""2"", _
IF(AND(((RC[-35]-RC[-36]+1)/(365/12))>=0,RC[-38]=""Y"",""0.3"",""0"")))))))))"

我在公式行上收到运行时错误“1004”“应用程序定义或对象定义错误”。我试图通过将它放在一个长行中来查看我的换行符是否是问题,但我仍然遇到同样的错误。

我意识到这可能是一个语法问题,但我正在努力找出问题所在。我知道这是一个不太理想(即丑陋)的解决方案,但考虑到这发生在更大的宏中,我希望让这个公式方法起作用。

如果有帮助的话;总体思路是根据两个标准得出一个值(5、4、2、1、.5 等)。第一个是(AG-AF+1)/(365/12) 是否在某个范围内,第二个是Column AD 中的简单YN 标志。前任。 (AG2-AF2+1)/(365/12) = 45AD2 = N 然后我希望 BP2 = 4

干杯!

【问题讨论】:

  • 这是一个很好的 UDF 候选 - 它基本上只是一个 Select Case
  • ""5"" 这些引号是否围绕所需的数字返回值?原始公式在这些位置没有...

标签: excel vba excel-formula


【解决方案1】:

编写为 Select Case 可能是个好主意,但请记住宏记录器可以成为您的朋友。只需在单元格 BP2 中记录输入公式,并将输出复制到 ActiveCell.FormulaR1C1 之后:

 ActiveCell.FormulaR1C1 = _
        "=IF(RC[-44]=""No Bonus"",1,IF(AND(((RC[-35]-RC[-36]+1)/(365/12))>=50,RC[-38]=""N""),5,IF(AND(((RC[-35]-RC[-36]+1)/(365/12))>=40,RC[-38]=""N""),4,IF(AND(((RC[-35]-RC[-36]+1)/(365/12))>=30,RC[-38]=""N""),2,IF(AND(((RC[-35]-RC[-36]+1)/(365/12))>=20,RC[-38]=""N""),1,IF(AND(((RC[-35]-RC[-36]+1)/(365/12))>0,RC[-38]=""N""),0.5,IF(AND(((RC[-35]-RC[-36]+1)/(365/12))>=2" & _
        "0,RC[-38]=""Y""),1,IF(AND(((RC[-35]-RC[-36]+1)/(365/12))>=15,RC[-38]=""Y""),2,IF(AND(((RC[-35]-RC[-36]+1)/(365/12))>=0,RC[-38]=""Y""),0.3,0)))))))))" & _
        ""

【讨论】:

    【解决方案2】:

    以这种方式尝试代码,其中每一行都是引号中的单独字符串。

    Worksheets("MyWorksheet").Range("BP" & LastRowExisting + 1 & ":" & "BP" & _
        LastRowNew).FormulaR1C1 = "=IF(RC[-44]=""No Bonus"",""1"", " & _
        "IF(AND(((RC[-35]-RC[-36]+1)/(365/12))>=50,RC[-38]=""N"",""5"", " & _
        "IF(AND(((RC[-35]-RC[-36]+1)/(365/12))>=40,RC[-38]=""N"",""4"", " & _
        "IF(AND(((RC[-35]-RC[-36]+1)/(365/12))>=30,RC[-38]=""N"",""2"", " & _
        "IF(AND(((RC[-35]-RC[-36]+1)/(365/12))>=20,RC[-18]=""N"",""1"", " & _
        "IF(AND(((RC[-35]-RC[-36]+1)/(365/12))>=0,RC[-38]=""N"",""0.5"", " & _
        "IF(AND(((RC[-35]-RC[-36]+1)/(365/12))>=20,RC[-38]=""Y"",""1"", " & _
        "IF(AND(((RC[-35]-RC[-36]+1)/(365/12))>=15,RC[-38]=""Y"",""2"", " & _
        "IF(AND(((RC[-35]-RC[-36]+1)/(365/12))>=0,RC[-38]=""Y"",""0.3"",""0"")))))))))"
    

    可以在字符串之间使用换行符(下划线),如How to Break and Combine Statements in Code 中的示例。

    【讨论】:

    • Scenography 感谢您的链接,我实际上已经浏览了那里并尝试了一些方法来清理单行与换行符上的语法。不幸的是,您答案中的代码也出现错误Run-time 1004
    【解决方案3】:

    打字&打字&打字

    打开您的工作簿,打开 VBE,插入一个新模块(或使用现有模块)并将以下代码粘贴到该模块中:

    Option Explicit
    
    Function Nested(Range1 As Range, Range2 As Range, _
        Range3 As Range, Range4 As Range) As Single
    
    '**** Customize BEGIN ******************
      'NOCase
      Const cStrSearch As String = "No Bonus"
      Const cSglYes As Single = 1
      'Period
      Const cDays As Integer = 365
      Const cMonths As Integer = 12
      'YesNo
      Const cStrYes As String = "Y"
      Const cStrNo As String = "N"
      'Title1 Source
      Const cSglN1 As Single = 50
      Const cSglN2 As Single = 40
      Const cSglN3 As Single = 30
      Const cSglN4 As Single = 20
      Const cSglN5 As Single = 0
      'Title1 Target
      Const cSglNA1 As Single = 5
      Const cSglNA2 As Single = 4
      Const cSglNA3 As Single = 2
      Const cSglNA4 As Single = 1
      Const cSglNA5 As Single = 0.5
      'Title2 Source
      Const cSglY1 As Single = 20
      Const cSglY2 As Single = 15
      Const cSglY3 As Single = 0
      'Title2 Target
      Const cSglYA1 As Single = 1
      Const cSglYA2 As Single = 2
      Const cSglYA3 As Single = 0.3
    '**** Customize END ********************
    
      If Range1.Value2 = cStrSearch Then
        Nested = cSglYes
        Exit Function
      End If
    
      Nested = (Range4.Value2 - Range3.Value2) / cDays / cMonths
    
      Select Case UCase(Range2.Text) 'Remove 'Ucase' function for case-sensitive
        Case cStrNo
          Select Case Nested
            Case Is >= cSglN1: Nested = cSglNA1
            Case Is >= cSglN2: Nested = cSglNA2
            Case Is >= cSglN3: Nested = cSglNA3
            Case Is >= cSglN4: Nested = cSglNA4
            Case Is > cSglN5: Nested = cSglNA5
            Case Else
              Nested = 0 'Change if necessary
          End Select
        Case cStrYes
          Select Case Nested
            Case Is >= cSglY1: Nested = cSglYA1
            Case Is >= cSglY2: Nested = cSglYA2
            Case Is >= cSglY3: Nested = cSglYA3
            Case Else
              Nested = 0 'Change if necessary
          End Select
        Case Else
          Nested = 0 'Change if necessary
      End Select
    
    '=IF(X2="No Bonus",1,
    'IF(AND(((AG2-AF2+1)/(365/12))>=50,AD2="N"),5,
    'IF(AND(((AG2-AF2+1)/(365/12))>=40,AD2="N"),4,
    'IF(AND(((AG2-AF2+1)/(365/12))>=30,AD2="N"),2,
    'IF(AND(((AG2-AF2+1)/(365/12))>=20,AD2="N"),1,
    'IF(AND(((AG2-AF2+1)/(365/12))>0,AD2="N"),0.5,
    'IF(AND(((AG2-AF2+1)/(365/12))>=20,AD2="Y"),1,
    'IF(AND(((AG2-AF2+1)/(365/12))>=15,AD2="Y"),2,
    'IF(AND(((AG2-AF2+1)/(365/12))>=0,AD2="Y"),0.3,0)))))))))
    End Function
    

    关闭 VBE 并在第二行 any 单元格中的工作表 (Excel) 中(X2AD2AF2AG2 除外)(例如 BP2 为你提到)使用以下公式:

    =NESTED($X2,$AD2,$AF2,$AG2)
    

    根据需要复制/粘贴公式。

    【讨论】:

    • VBasic2008 我很欣赏这里的替代方法。我没有测试和实施,因为“通过 vba 放入单元格的公式”是长期自动化过程的一部分。下次我做类似的事情时,我会试试你的方法!
    • 感谢您的信任,尽管我不应该得到它,因为我现在才意识到我错过了理解这个问题。对不起。
    猜你喜欢
    • 1970-01-01
    • 2019-06-23
    • 2022-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多