#ЗНАЧЕНИЕ!Ошибка в ячейке, содержащей успешно скомпилированную функцию VBA - PullRequest
0 голосов
/ 13 июня 2019

Я использую VBA для интеграции в Excel. У меня есть множество переменных, необходимых для процесса интеграции в организованной таблице на листе, которая будет изменяться по мере необходимости. Я написал следующий код, чтобы выполнить это, и успешно отладил указанный код, чтобы он компилировался без ошибок.

Dim dIdt As Range
Dim Isnp As Range
Dim Tau As Range

Dim A As Range
Dim B As Range
Dim C As Range
Dim D As Range


Function Iscr(t)
Set dIdt = Worksheets("Sheet1").Range("F11").Value
Set Isnp = Worksheets("Sheet1").Range("F14").Value
Set Tau = Worksheets("Sheet1").Range("F13").Value
Iscr = (dIdt * t) + (Isnp * (Exp((-t) / Tau)))
End Function

Function Econd1A(t)
Set A = Worksheets("Sheet1").Range("B17").Value
Set B = Worksheets("Sheet1").Range("B18").Value
Set C = Worksheets("Sheet1").Range("B19").Value
Set D = Worksheets("Sheet1").Range("B20").Value
Econd1A = A + (B * (Log(Iscr(t)))) + (C * (Iscr(t))) + (D * (Iscr(t) ^ (1 / 2)) * Iscr(t))
End Function

Function Econd1(x0, t1, t2)

'define range of integral
int_range = t2 - t1

'discretize the integral into n slices dt wide
n = 1000
dt = int_range / n

'initialize variables
ta = t1
tb = ta + dt
Econd1 = x0

'calculate areas using trapezoidal rule

'sum area under curve of each slice
For j = 1 To n
Econd1 = Econd1 + (tb - ta) * (Econd1A(ta) + Econd1A(tb)) / 2
ta = tb
tb = ta + dt
Next

End Function

Я сейчас в недоумении в отношении отладки, поскольку ошибка, похоже, не связана с VBA.

Ожидаемый вывод ячейки - 0,0127, но вместо этого он дает # ЗНАЧЕНИЕ! ошибка.

Ответы [ 2 ]

1 голос
/ 13 июня 2019

Механизм вычислений Excel оборачивает любые ошибки, возникающие в пользовательской функции (UDF - пользовательская функция, вызываемая из ячейки рабочего листа), и выдает ошибку ячейки #VALUE вместо того, чтобы взорваться, как это обычно происходит с испорченным кодом VBA.Без какой-либо обработки ошибок отладка UDF может быть «забавной».

Реализация обработки ошибок:

Public Function MyUDF(args)
    On Error GoTo ErrHandler
    '...code...
    Exit Function
ErrHandler:
    Debug.Print Err.Description
    Stop ' halts execution
    Resume 'jumps back to the error-raising statement
End Function

Иметь панель непосредственного доступа видимой (Ctrl +G) в VBE, затем вычислите рабочий лист, который вызывает UDF, с несколькими возможными входами, охватывающими все граничные случаи - с особым вниманием к значениям, которые могут привести к переполнению и делению на ноль ошибки.

Когда выполнение останавливается по ключевому слову Stop, нажмите клавишу F8, чтобы запустить оператор Resume, который приведет вас прямо к утверждению, вызвавшему ошибку - оттуда вы можете проверить всезадействованные переменные, и шаг за шагом проходите по функции, чтобы проверить свою математику при ее выполнении - и вы можете переместить желтую строку «текущая инструкция» обратно к уже выполненному оператору, чтобы перезапустить ее,тоже - просто перетащите желтую стрелку туда, где вы хотите, чтобы она была внутри функции, или щелкните правой кнопкой мыши инструкцию и выберите «установить следующую инструкцию».

Eкод обработки ошибок / отладки может быть удален, как только вы знаете , функция работает должным образом, и вы согласны с ней, возвращая ошибку #VALUE с недопустимыми аргументами.

1 голос
/ 13 июня 2019
Function Iscr(ByVal t As Double) As Double
    Dim dIdt As Double, Isnp As Double, Tau As Double
        dIdt = Worksheets("Sheet1").Range("F11").Value
        Isnp = Worksheets("Sheet1").Range("F14").Value
        Tau = Worksheets("Sheet1").Range("F13").Value
        Iscr = (dIdt * t) + (Isnp * (Exp((-t) / Tau)))
End Function

Function Econd1A(ByVal t As Double) As Double
    Dim A As Double, B As Double, C As Double, D As Double
        A = Worksheets("Sheet1").Range("B17").Value
        B = Worksheets("Sheet1").Range("B18").Value
        C = Worksheets("Sheet1").Range("B19").Value
        D = Worksheets("Sheet1").Range("B20").Value
        Econd1A = A + (B * (Log(Iscr(t)))) + (C * (Iscr(t))) + (D * (Iscr(t) ^ (1 / 2)) * Iscr(t))
End Function

Function Econd1(ByVal x0 As Double, ByVal t1 As Double, ByVal t2 As Double) As Double
Dim int_range As Integer
    int_range = t2 - t1
    n = 1000
    dt = int_range / n
    ta = t1
    tb = ta + dt
    Econd1 = x0
        For j = 1 To n
            sEcond1 = sEcond1 + (tb - ta) * (Econd1A(ta) + Econd1A(tb)) / 2
            ta = tb
            tb = ta + dt
        Next j
Econd1 = sEcond1
End Function
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...