2

I am writing and re-writing Excel VBA code to make some engineering analysis easier for myself and the others at my company. So the goal is to make it easy for others, not to be integrated into other code or purposes outside our own Excel work.

The problem: a few of the macros will add a custom function to a worksheet cell, bring up the function dialog for inputs, but then when completed, come up with a Value error, stating A value used in the formula is of the wrong data type. Based on this, I believe the issue arises when my function uses a Variant or Range type variable. Some of these functions only give this error via certain input types.

HOWEVER, in every single case, using the function dialog Not in the macro works fine, as does typing the formula in manually. Additionally, all you have to do is double-click on the error cell to edit it, change nothing, press enter, and it's fine!

My macros themselves are as simple as:

Sub NewSTC_dialog()
    ActiveCell.FormulaR1C1 = "=sheetname.xlsm!NewSTC()"
    Application.Dialogs(xlDialogFunctionWizard).Show
End Sub  

My functions have more to them, but the situation is different for different functions, and the functions themselves work fine, so it is preferable to have a solution that applies to the macros rather than within the functions. If I must, I can go through each situation individually or come up with a simplified function that has the same issue to give as an example.

My best workaround so far (I cannot re-find the website were I found this particular solution):

Sub Recalculate()
    ActiveCell.Replace What:="=", Replacement:="="
End Sub  

Set to a convenient shortcut, and it works great. However, as mentioned above, the goal is to make this easy for everyone else, which would mean not requiring anything additional to have the formula work. Unfortunately, calling this from within the initial macro will not work. In fact, nothing located after the dialog call will run. I tried using On Error Resume Next and it still won't run anything after the dialog call.

Some options searched and tried:
How to refresh cells in Excel 2010 using VBA? and links within that - as mentioned, nothing located after the dialog call will run, thus won't reach these adjustments. Putting before the dialog call also doesn't help. Putting the dialog call in between the false and true statements makes the false apply, then never runs the true statement.
http://www.excelforum.com/excel-general/471632-formula-do-not-work-until-edited.html - Excel is not set to manual
http://blog.contextures.com/archives/2012/02/16/excel-formulas-not-calculating/ - SUMIF is not involved

This is all on Excel 2010, Windows 7 Professional.

EDIT: Here is an example that creates this behavior. This is similar to the behavior of two of my functions, but not to all of them, so again, I would much prefer the solution be in the macro, not the function. This is just for anybody else's testing purposes.

Function LetNum(input1 As Variant, input2 As Variant) As Integer
    If input1 = "A" Or input1 = "a" Then
        input1 = 100
    ElseIf input1 = 10 Then
        input1 = -10
    End If
    If input2 = "B" Or input2 = "b" Then
        input2 = 200
    ElseIf input2 = 10 Then
        input2 = -1000
    End If
    LetNum = input1 + input2
End Function
Sub LetNum_dialog()
    ActiveCell.FormulaR1C1 = "=LetNum()"
    Application.Dialogs(xlDialogFunctionWizard).Show
End Sub

In this situation, typing A and 2 into the dialog box in that order works, but 2 into the second then A into the first doesn't. Additionally, typing B in the second box never works. In all situations, clicking to edit, changing nothing, and hitting enter, fixes it. Additionally, any situation in the dialog box if you bring it up without the macro works fine.

Also, I'm aware this case works better if you input it with quotes, but excel automatically changes it correctly, and not all my functions are string issues.

EDIT 2:
Tim's answer is a great step in the right direction! However, if anybody can come up with a solution that doesn't involve ignoring all errors, that would be more ideal due to some desired error-throwing being ignored. I will look into handling errors differently in the meantime.

Community
  • 1
  • 1
ceegers
  • 31
  • 7
  • 1
    It would help to provide a simple example of a function which reliably causes the problem you're seeing. – Tim Williams Sep 23 '15 at 18:06
  • Alright, edited with example. – ceegers Sep 23 '15 at 18:36
  • OK I see it now - the #VALUE! error only shows up in certain cases and disappears if the edit the cell but make no changes. New to me. – Tim Williams Sep 23 '15 at 18:55
  • ? https://fastexcel.wordpress.com/2014/01/26/inserting-a-udf-and-launching-the-function-wizard-from-vba/ – Tim Williams Sep 23 '15 at 18:58
  • Heh, that is an interesting potential solution... unfortunately doesn't seem to work for this situation (tried increasing to a full second for the heck of it too... it does indeed wait a second, but no dice on improved results) – ceegers Sep 23 '15 at 19:21
  • I think the issue is within the Function Wizard itself - calling it a different way doesn't seem to make any difference... – Tim Williams Sep 23 '15 at 20:27
  • For me it does: If I type =LetNum( (or my actual functions) into a cell, then click on the fx button, all of these situations work just fine. – ceegers Sep 23 '15 at 20:29

1 Answers1

1

The issue seems to be that any error triggered in your UDF effectively "disables" the Function Wizard: note that in cases where you get #VALUE! error, the Show() method never returns any value, and any lines following the call to Show() are not executed.

The only thing which resolved this in my testing was to add a line to the function which skips any errors when the Function Wizard is open:

Dim bSettingUp As Boolean

Function LetNum(input1 As Variant, input2 As Variant) As Integer

    If bSettingUp Then On Error Resume Next

    If input1 = "A" Or input1 = "a" Then
        input1 = 100
    ElseIf input1 = 10 Then
        input1 = -10
    End If
    If input2 = "B" Or input2 = "b" Then
        input2 = 200
    ElseIf input2 = 10 Then
        input2 = -1000
    End If
    LetNum = input1 + input2
End Function

Sub LetNum_dialog()
    ActiveCell.Formula = "=LetNum()"
    bSettingUp = True
    Debug.Print Application.Dialogs(xlDialogFunctionWizard).Show()
    bSettingUp = False
End Sub

I'm aware that you'd rather not alter your functions ,but this was the only work-around I could find.

Tim Williams
  • 154,628
  • 8
  • 97
  • 125
  • I'm okay with that kind of function-altering because it can be applied fairly universally. Thank you, I will try this later! – ceegers Sep 23 '15 at 21:22
  • This works for every one of my functions! The one thing that makes this not ideal is that now purposeful errors are being ignored, which may mean I need to look into sending errors differently. But yes, very useful, thank you! – ceegers Sep 23 '15 at 22:00