Подтвердить что ты не робот

Задайте значение ячейки из функции

Содержимое ячейки A1 =test(2) где test - это функция:

Function test(ByRef x As Double) As Double
  Range("A2") = x
  test = x * x
End Function

Можете ли вы объяснить, почему это дает # #VALUE! в ячейке A1 и ничего в ячейке A2? Я ожидал, что A2 будет содержать 2 а A1 будет содержать 4. Без строки Range("A2") = x функция работает как ожидалось (возводя в квадрат значение ячейки).

Что действительно сбивает с толку, так это если вы calltest test с подпрограммой calltest тогда это calltest

Sub calltest()
  t = test(2)
  Range("A1") = t
End Sub

Function test(ByRef x As Double) As Double
  Range("A2") = x
  test = x * x
End Function

Но это не

Function test(ByRef x As Double) As Double
  Range("A2") = x
End Function
4b9b3361

Ответ 1

Когда вы вызываете функцию из ячейки рабочего листа, вы эффективно используете функцию как пользовательскую функцию, которая имеет ограничения, как описано здесь:

http://support.microsoft.com/kb/170787

В тексте есть строка:

Любые изменения среды должны быть сделаны с помощью подпрограммы Visual Basic.

Интересно, как они используют это слово, а не должны. Интересно, знал ли автор КБ, что изменения в среде могут произойти из-за функции VBA.

Теперь, когда вы вызываете функцию из другой Sub/Function VBA, она обрабатывается по-другому. Из справочной документации (извините, я не смог найти ссылку на веб-страницу - в основном в VBE выделите слово Function и нажмите F1):

Как и процедура Sub, процедура Function - это отдельная процедура, которая может принимать аргументы, выполнять серию операторов и изменять значения своих аргументов. Однако, в отличие от процедуры Sub, вы можете использовать процедуру Function в правой части выражения так же, как и любую встроенную функцию, такую как Sqr, Cos или Chr, когда вы хотите использовать значение, возвращаемое функцией,

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

На самом деле это довольно интересно, поскольку Excel может вызывать функцию с ограничением "только для чтения" для среды Excel.

Я думаю, что, в конце концов, Excel может вызывать функцию из ячейки рабочего листа не так, как VBA. Когда вы вызываете его из ячейки, он считается определяемой пользователем функцией, которая включает ограничения на изменение среды Excel. Если при вызове из VBA (где первоначально вызывающие из цепочки вызовов из VBA), он имеет всю власть Суб делает, плюс он может возвращать значение.

Ответ 2

Из-за Function оснований, которые утверждают, что вы не можете изменить или установить ячейки листа. Вам нужно удалить строку с помощью Range("A2") = x

EDIT Некоторая дополнительная ссылка (которая, я считаю, всегда полезна для тех, кто хочет анализировать тему UDF): Создание пользовательских функций Microsoft

Ответ 3

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

Вот простой пример. Функция UDF принимает два аргумента A и B и возвращает их произведение A * B. Но что интересно, он возвращает результат в соседней ячейке справа от ячейки, в которую мы ввели формулу.

Поместите этот код в стандартный модуль VBA:

Function UDF_RectangleArea(A As Integer, B As Integer)
    Dim MagicSpell As String
    MagicSpell = "Adjacent(" & Application.Caller.Offset(0, 1).Address(False, False) & "," & A & "," & B & ")"
    Evaluate MagicSpell
    UDF_RectangleArea = "Hello world"
End Function

Private Sub Adjacent(CellToChange As Range, A As Integer, B As Integer)
    CellToChange = A * B
End Sub

Теперь введите B2 формулу: =UDF_RectangleArea(3,4)

enter image description here

Функция возвращает результаты в двух ячейках: "Hello world" в B2 (что неудивительно) и область прямоangularьника в C2 (это кролик из шляпы). Оба результата, а также место появления "кролика" могут быть легко настроены. Работа выполняется командой VBA EVALUALTE. В этом случае значение переменной MagicSpell становится равным Adjacent(C2,3,4), которое запускается из UDF, прежде чем возвращается результат UDF. Веселиться!

Ответ 4

Я адаптировал ваш код для работы со строками, функциями и всем остальным промежуточным, я надеюсь (все еще тестирую).

В результате тестирования возникает множество вопросов, но в первую очередь приходят 2:

Какие еще способы вы могли бы использовать для выполнения/обработки параметров и возврата желаемых результатов;

а. Как я сделал б. Не так, как я сделал (то есть по-другому).

Function MOVEME27(a As Variant, b As Variant, Optional CELLR As Variant, Optional cellq As Variant) '21/05/2018 works copied to ar4' 03/06/2019 23:30 was cellr as range , cellq as range - changed to variants
 Dim WTVR1 As Variant '' ''20/05/2019'' '09/06/2019 Code by S Tzortzis/David Wooley
 Dim WTVR2 As Variant
 Dim P As String
 Dim P1 As String
 Dim bb As String
 Dim bb1 As String
 Dim A1 As Long
 Dim A2 As Long

 Dim c As String

 'x' a = Evaluate(a)
P = Chr(34) & a & Chr(34)
P2 = Chr(34) & [P] & Chr(34)

bb = Chr(34) & b & Chr(34)
bb1 = Chr(34) & [bb] & Chr(34)

c = Chr(34) & CELLR & Chr(34)
f = Chr(34) & callq & Chr(34)


'P2 = Chr(34) & "'''" & [P] & "'''" & Chr(34)
'p1 = Chr(34) & p & Chr(34)

''WTVR1 = "MOVEUS1(" & Application.Caller.Offset(0, 2).Address(False, False) & "," & Chr(34) & P2 & Chr(34) & "," & b & ")"
   WTVR1 = "MOVEUS11h(" & Application.Caller.Offset(0, 2).Address(False, False) & "," & [P2] & "," & [bb1] & ")"
Evaluate WTVR1


WTVR2 = "MOVEUS22h(" & Application.Caller.Offset(0, 1).Address(False, False) & "," & [P2] & "," & [bb1] & ")" ' used or be adjacent - maybe redo rhat pr put a GO TO sub. '' ''20/05/2019''

Evaluate WTVR2

A1 = cellq.Row
A2 = cellq.Column

CELLRR = Chr(34) & CELLR & Chr(34)
CELLRR1 = Chr(34) & [CELLRR] & Chr(34)
cellqq = Chr(34) & cellq & Chr(34)
cellqq1 = Chr(34) & [cellqq] & Chr(34)


''wtvr3 = "CopyFrom.Parent.Evaluate CopyOver234h(" & c & "," & f & ")" ''''20190531 1929
wtvr31 = "MOVEUS33h(" & Application.Caller.Offset(A1 - ActiveCell.Row + 1, A2 - ActiveCell.Column).Address(False, False) & "," & [CELLRR] & "," & [cellqq] & ")"

    Evaluate wtvr31

MOVEME27 = "Hello world       " & " / " & WTVR1 & " / " & WTVR2 & "\\\\\/////" & wtvr31 & "\\\\\/////---" & ActiveCell.Row - A1 & "//////---" & ActiveCell.Column - A2

' DO AS WHATVER = "MOVEUS3(" APPLICATION.CALLER.OFFSET(THE ROW & COLUMN IE CELL         YOU REFERENCES IN a as variant (copy from)'
    'with ="" in sub 30052019 19:28

    'CopyFrom.Parent.Evaluate "CopyOver2(" & CELLR.Address(False, 1) & "," &              CELLR.Address(False, False) & ")"  ''''2019050 1929



    End Function

    Private Sub MOVEUS11h(CELL1 As Range, G1 As Variant, G2 As Variant)

        '[ak333] = a


        CELL1 = Chr(34) & G1 & Chr(34) & "B" & "//" & G2


    End Sub


    Private Sub MOVEUS22h(CELL2 As Range, G3 As Variant, G4 As Variant)

        CELL2 = Chr(34) & G3 & Chr(34) & "<>" & G4

    End Sub

    '' with chr(34) arond the p and a in sub or fucntion changes behavior. thinking of doing if a is string, then a=x , x as string, if not kep as variant
    ''27/05/2019 :(

    '''''30/05/2019 .....'''''''


    '------------------------------------------------------------------------------- ADD THIS 30052019 -------------------------------
    'private sub Movus3(cellfrom as range, cellto as range)
    'End Sub

    Private Sub moveus33h(cell3 As Range, CopyFrom As Variant, copyTo As Variant) ''''2019050 1929 ''' 03062019 change ema back to as Range here. :)
       '' copyTo.Value = CopyFrom.Value ''''2019050 1929

       ''CopyFrom.Value = ""

       cell3 =  CopyFrom  'Chr(34) & CopyFrom & Chr(34)

    End Sub ''''2019050 1929