自定义函数在VBA中工作,但在Excel单元格中调用时无效

时间:2017-04-24 01:08:26

标签: vba excel-vba excel

我编写了一个自定义VBA函数,当我在VBA中调用它时它将起作用。 e.g。

Sub test()

    Debug.Print calculate_acr_bands_data("recommended_acr", "22/11/2014", 2.67, "B23:C27", 50, 2.14, 1, 0.107, 3.89, "22/02/2021")

End Sub

输出......

0.01

但是,当我在excel工作簿中的单元格内调用完全相同的函数时。我收到错误"此公式中使用的值是错误的数据类型"。这没有任何意义,因为我刚刚证明该公式与VBA中的完全相同的输入一起工作。

enter image description here

如果您想查看源代码,我已将我的回购上传到我的GitHub帐户...

https://github.com/Joshua-W-Adams/vba-wall-loss-vs-time

感谢您的帮助。

更新

功能已发布在以下...

'Description: Calculate database of wall loss vs time information so relevant parameters can be returned
Public Function calculate_acr_bands_data(return_parameter As String, last_inspection_date As Date, last_inspection_date_wall_loss As Double, _
    acr_bands_array_text As String, nominal_wall_thickness As Double, _
    minimum_allowable_wall_thickness As Double, current_acr As Double, actual_cr As Double, current_rl As Double, current_end_of_life As Date) As Variant

    'Create copy of data range so nominal wall thickness value is not overriden
    Dim acr_bands_array As Range:                   Set acr_bands_array = ThisWorkbook.Worksheets("Wall_Loss_Vs_Time_Graph").Range(acr_bands_array_text)
    Dim n As Integer:                               n = 0
    Dim acr_bands_array_size As Integer:            acr_bands_array_size = acr_bands_array.Rows.Count
    Dim return_data_array() As BAND_ARRAY_CLASS
    Dim current_band_position As Integer
    Dim recommended_acr As Double
    Dim recommended_rl As Double
    Dim forecast_wall_loss As Double
    Dim recommended_end_of_life As Date

    'Update band array with fail FFS wall thickness of current cml
    acr_bands_array(acr_bands_array.Rows.Count, 1) = nominal_wall_thickness - minimum_allowable_wall_thickness

    'Determine current band that the last inspection date wall loss falls into
    For n = 1 To acr_bands_array_size - 1

        If last_inspection_date_wall_loss < acr_bands_array(n + 1, 1) Then

            current_band_position = n
            Exit For

        End If

    Next n

    'Push first row to array (last inspection date details)
    return_data_array = push_to_array(return_data_array, "Band Data Points", Format(last_inspection_date, "Short Date"), last_inspection_date_wall_loss, acr_bands_array(current_band_position, 2))

    'Debug.Print return_data_array(0).graph_name
    'Debug.Print return_data_array(0).date_value
    'Debug.Print return_data_array(0).wall_loss
    'Debug.Print return_data_array(0).acr

    'Push all corrosion rate band data
    If n <> 0 Then 'If a hole out is not detected

        For n = current_band_position To acr_bands_array_size - 1

            return_data_array = push_to_array(return_data_array, _
                "Band Data Points", _
                Format(DateAdd("d", (acr_bands_array(n + 1, 1) - return_data_array(UBound(return_data_array)).wall_loss) / acr_bands_array(n, 2) * 365, return_data_array(UBound(return_data_array)).date_value), "Short Date"), _
                acr_bands_array(n + 1, 1), _
                acr_bands_array(n, 2))

        Next n

    End If

    'Push data for current wall loss as of today
    For n = 1 To UBound(return_data_array) - 1

        If Now() < return_data_array(n + 1).date_value Then

            return_data_array = push_to_array(return_data_array, _
                "Band Data Points", _
                Format(Now(), "Short Date"), _
                return_data_array(n).acr * DateDiff("d", return_data_array(n).date_value, Now()) / 365 + return_data_array(n).wall_loss, _
                return_data_array(n).acr)

                'Dim rsize As Integer
                'rsize = UBound(return_data_array)
                'Debug.Print return_data_array(rsize).graph_name
                'Debug.Print return_data_array(rsize).date_value
                'Debug.Print return_data_array(rsize).wall_loss
                'Debug.Print return_data_array(rsize).acr

            Exit For

        End If

    Next n

    recommended_acr = (return_data_array(UBound(return_data_array) - 1).wall_loss - return_data_array(UBound(return_data_array)).wall_loss) _
                        / (return_data_array(UBound(return_data_array) - 1).date_value - return_data_array(UBound(return_data_array)).date_value)
    forecast_wall_loss = return_data_array(UBound(return_data_array)).wall_loss
    recommended_end_of_life = return_data_array(UBound(return_data_array) - 1).date_value
    recommended_rl = DateDiff("d", return_data_array(UBound(return_data_array) - 1).date_value, Now()) / 365

    Debug.Print recommended_acr
    Debug.Print forecast_wall_loss
    Debug.Print recommended_end_of_life
    Debug.Print recommended_rl

    'Debug.Print recommended_rl

    'Add additional graph data for reference
    return_data_array = push_to_array(return_data_array, "Today", DateValue(Format(Now(), "Short Date")), 0, 0)
    return_data_array = push_to_array(return_data_array, "Today", DateValue(Format(Now(), "Short Date")), nominal_wall_thickness, 0)

    return_data_array = push_to_array(return_data_array, "Recommended RL", DateValue(Format(recommended_end_of_life, "Short Date")), 0, 0)
    return_data_array = push_to_array(return_data_array, "Recommended RL", DateValue(Format(recommended_end_of_life, "Short Date")), nominal_wall_thickness - minimum_allowable_wall_thickness, 0)

    return_data_array = push_to_array(return_data_array, "Recommended ACR", DateValue(Format(Now(), "Short Date")), forecast_wall_loss, recommended_acr)
    return_data_array = push_to_array(return_data_array, "Recommended ACR", DateValue(Format(recommended_end_of_life, "Short Date")), nominal_wall_thickness - minimum_allowable_wall_thickness, 0)

    return_data_array = push_to_array(return_data_array, "Current RL", current_end_of_life, 0, 0)
    return_data_array = push_to_array(return_data_array, "Current RL", current_end_of_life, nominal_wall_thickness, 0)

    return_data_array = push_to_array(return_data_array, "Current ACR", DateValue(Format(last_inspection_date, "Short Date")), last_inspection_date_wall_loss, current_acr)
    return_data_array = push_to_array(return_data_array, "Current ACR", DateValue(Format(current_end_of_life, "Short Date")), nominal_wall_thickness, current_acr)

    return_data_array = push_to_array(return_data_array, "Actual CR", DateValue(Format(last_inspection_date, "Short Date")), last_inspection_date_wall_loss, actual_cr)
    return_data_array = push_to_array(return_data_array, "Actual CR", DateAdd("d", (nominal_wall_thickness - last_inspection_date_wall_loss) / actual_cr * 365, last_inspection_date), nominal_wall_thickness, 0)

    return_data_array = push_to_array(return_data_array, "Actual RL", DateAdd("d", (nominal_wall_thickness - last_inspection_date_wall_loss) / actual_cr * 365, last_inspection_date), 0, 0)
    return_data_array = push_to_array(return_data_array, "Actual RL", DateAdd("d", (nominal_wall_thickness - last_inspection_date_wall_loss) / actual_cr * 365, last_inspection_date), nominal_wall_thickness, 0)

    return_data_array = push_to_array(return_data_array, "Fail FFS", DateValue(Format(last_inspection_date, "Short Date")), nominal_wall_thickness - minimum_allowable_wall_thickness, 0)
    return_data_array = push_to_array(return_data_array, "Fail FFS", IIf(recommended_end_of_life > current_end_of_life, recommended_end_of_life, current_end_of_life), nominal_wall_thickness - minimum_allowable_wall_thickness, 0)

    return_data_array = push_to_array(return_data_array, "Nominal Wt", last_inspection_date, nominal_wall_thickness, 0)
    return_data_array = push_to_array(return_data_array, "Nominal Wt", IIf(recommended_end_of_life > current_end_of_life, recommended_end_of_life, current_end_of_life), nominal_wall_thickness, 0)

    'Return requested parameter to user
    If return_parameter = "database" Then

        calculate_acr_bands_data = return_data_array

    ElseIf return_parameter = "recommended_acr" Then

        calculate_acr_bands_data = Round(recommended_acr, 2)

    ElseIf return_parameter = "forecast_wall_loss" Then

        calculate_acr_bands_data = Round(forecast_wall_loss, 2)

    ElseIf return_parameter = "recommended_rl" Then

        calculate_acr_bands_data = Round(recommended_rl, 2)

    Else

        calculate_acr_bands_data = Null

    End If

End Function

'Description: Pass array and values to push
Function push_to_array(bands_array As Variant, graph_name As String, date_value As Date, wall_loss As Double, acr As Double) As Variant

    Dim size As Integer: size = UBound(bands_array) + 1

    ReDim Preserve bands_array(size)

    Set bands_array(size) = New BAND_ARRAY_CLASS

    With bands_array(size)
        .graph_name = graph_name
        .wall_loss = wall_loss
        .date_value = date_value
        .acr = acr
    End With

    push_to_array = bands_array

End Function

1 个答案:

答案 0 :(得分:1)

您的代码不能用作UDF,因为UDF无法为除调用UDF之外的任何单元格赋值(并且通过设置函数的返回值来指定其值)。

所以,因为你的行

acr_bands_array(acr_bands_array.Rows.Count, 1) = nominal_wall_thickness - minimum_allowable_wall_thickness

正在尝试修改Excel工作表的状态,它会崩溃并且应该向调用该函数的单元格返回#VALUE!错误。

我不确定为什么会出现"A value used in this formula is of the wrong data type"错误 - UDF返回任何类型的错误消息只是非常,这只是错误值。