0

I have a custom function which I've written in VBA.

At the start of the code, the function checks that the input data is in the right format and displays an error message if not.

The problem I have is that if I break the input data (e.g. put some text in a cell which the function requires to be numeric), then every cell which contains my function and references that data will display an error message. So I get loads of error messages all at once.

I'd like to be able to change my function so it only displays the error message if the user is actively editing cell (similar to usual excel function error messages).

I thought I'd be able to use something like Worksheet_Change but I don't see how I could embed that in my function.

Another option would be to only allow 1 error message at a time but no idea how to set that up either.

Any ideas would be appreciated!

Here's the start of my code with the first input data check and error message:

Public Function OnLevelFactor(effective_dates As Range, rate_changes As Range, OnLevelYear As 
Range) As Double

'do they only contain numbers (/dates)?
If (WorksheetFunction.Count(effective_dates) + WorksheetFunction.CountBlank(effective_dates)) <> effective_dates.Count() Then
    Msg = "Dates " & effective_dates.Address & " must be numeric."
    MsgBox Msg, , "Error: OnLevelFactor", Err.HelpFile, Err.HelpContext
    Exit Function
End If

'rest of code

End Function

EDIT

I found this code which works pretty well:

Public Function OnLevelFactor(effective_dates As Range, rate_changes As Range, OnLevelYear As 
    Range) As Double

'Check if cell is being actively edited before triggering error-handling
Dim caller As Range
Set caller = Application.caller
MsgBoxTrigger = Not Intersect(caller, Application.ActiveCell) Is Nothing

And then each error check begins with "If MsgBoxTrigger Then". Any thoughts on this approach would be appreciated.

1
  • 4
    Don't use MsgBox in your UDF but return error text to the calling cell? Commented Oct 14, 2024 at 20:41

2 Answers 2

2

The correct way of error handling in Excel user defined functions (UDF) is presented below:

Public Function OnLevelFactor(effective_dates As Range, rate_changes As Range, _
  OnLevelYear As Range) As Variant
  On Error GoTo UnknownErrorHandler
  If (WorksheetFunction.Count(effective_dates) + WorksheetFunction.CountBlank(effective_dates)) <> effective_dates.Count() Then
      OnLevelFactor = CVErr(xlErrValue) ' #VALUE!
      Exit Function
  End If

  'rest of code
  
ExitFunction:
  Exit Function
UnknownErrorHandler:
  OnLevelFactor = CVErr(xlErrUnknown)
  Resume ExitFunction
End Function

The function return type should be Variant. The error constants are defined in the XlCVError enum.

Following this way UDF works the same as standard Excel functions.

If you need to validate user input, you can use Excel's Data Validation feature or handle the Workbook_Change event.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, I'll try CVErr. I'd also like to be able to replicate Excel's "There's a problem with this formula." msgbox though
"I'd also like to be able to replicate..." - don't waste your time, it's not possible to replicate. The only way here is the Data Validation feature.
1

You can also send this message to a cell comment. You can choose a cell with a comment to read and don't have to enter information in MsgBox from which cell the message comes.

Public Function OnLevelFactor(effective_dates As Range, rate_changes As Range, OnLevelYear As Range) As Variant
With Application.ThisCell
    'do they only contain numbers (/dates)?
    If WorksheetFunction.Count(effective_dates) + WorksheetFunction.CountBlank(effective_dates) <> effective_dates.Count Then
    
        If Not .Comment Is Nothing Then .Comment.Delete
        .AddComment "Dates " & effective_dates.Address & " must be numeric."
        ' MsgBox Msg, , "Error: OnLevelFactor", Err.HelpFile, Err.HelpContext
        OnLevelFactor = CVErr(xlErrValue)
        Exit Function
    Else
        If Not .Comment Is Nothing Then .Comment.Delete
    End If
End With

'rest of code
    OnLevelFactor = 1
End Function

1 Comment

Nice approach !

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.