Сложный вложенный IF и формула, записываемая на лист VBA - PullRequest
0 голосов
/ 31 октября 2018

В настоящее время у меня есть сложная формула, которую я пытаюсь поместить в ячейку через 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) находится в определенном диапазоне, а второй - простой флаг Y или N в Column AD. Ex. (AG2-AF2+1)/(365/12) = 45 и AD2 = N тогда я бы ожидал BP2 = 4.

Ура!

Ответы [ 3 ]

0 голосов
/ 31 октября 2018

Писать как 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)))))))))" & _
        ""
0 голосов
/ 31 октября 2018

Набор текста & Набор текста & Набор текста

Откройте вашу рабочую книгу, откройте 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 и на листе (Excel) в любой ячейке во втором ряду (кроме X2, AD2, AF2, AG2) (например, BP2 как вы упомянуто) используйте следующую формулу:

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

Скопируйте / вставьте формулу по мере необходимости.

0 голосов
/ 31 октября 2018

Попробуйте код таким образом, где каждая строка представляет собой отдельную строку в кавычках.

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"")))))))))"

Символ продолжения строки (подчеркивание) можно использовать между строками, как в примере на Как разбить и объединить операторы в коде .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...