简体   繁体   中英

Call excel solver in VBA functions *without* direct reference to cells?

How to call solver in a VBA function without reference to existing cells? I don't want to have to reserve cells for these purely intermediate parameters.

Public Function calcSomething(param1 As Double, param2 As Double) As Double
' do something
' need to invoke solver to obtain some intermediate params
    Dim intermediate_param As Double
'hopefully should be like intermediate_param = calcWithSolver(param1, param2)
'do something
End Function

Public Function calcWithSolver(param1 As Double, param2 As Double) As Double
' how to call solver here without direct reference to existing cells?
End Function

The tutorials I found online that played with SolverAdd functions all seemed to require references to cells that already exist. Is there a way to avoid this?

As an alternative, you could try this very simple solver which uses the bisection method and works well for the majority of even complex cases.

It doesn't have the flexibility of the excel solver, and can't deal with deeply nested references which span a workbook (your solution parameter needs to be uniquely defined from within a single cell). But providing you can arrange this it has the advantage of auto-calculating tables which is not possible with the Excel Solver.

The code can also be modified to find maxima and minima by changing the bisection conditions (exercise for the user)

Function Bisect(F_ref As Range, y As Double, xname As String, xmin As Double, xmax As Double, Optional ytol As Double, Optional iter As Double)

'Finds the solution for x of the equation F(x) = y using the bisection method
'Requires a function F(x) and an interval [xmin, xmax] (in which F(x) is continuous) containing one and only one solution.

'F_ref     - reference to single cell containing the function f(x). NOTE : Do not specify the function directly as an input. Cell referenced needs to contain all the dependencies on x directly (no 
'y         - value of F(x) required
'xname     - reference text name for x in F_ref
'xmin,xmax - maximum and minimum values of xname that solution is known to lie within
'ytol      - tolerance to within which solution is needed [optional, default 1e-3]
'iter      - maximum number of iterations [optional, default 20]
'            returns #TOL! if tolerance not met. Increase ytol or increase iter

Dim fun As String, grad As Double, count As Integer

If ytol = 0 Then ytol = 0.001
If iter = 0 Then iter = 20

fun = F_ref.Formula & "-" & y
grad = (Evaluate(Replace(fun, xname, xmax)) - Evaluate(Replace(fun, xname, xmin))) / (xmax - xmin)

For count = 1 To iter
    x = (xmax + xmin) / 2
    y = Evaluate(Replace(fun, xname, x))
    If (y * y) < (ytol * ytol) Then Exit For
    If grad > 0 Then
        If y > 0 Then xmax = x
        If y < 0 Then xmin = x
    Else
        If y < 0 Then xmax = x
        If y > 0 Then xmin = x
    End If
Next count
If count > iter Then x = "#TOL! " & x
Bisect = x
End Function

As an example in excel if cell A1 contains the equation

=2*LN(B1) + B1

then the function call

=Bisect(A1, 2, "B1", 1, 2)

solves the equation 2ln(x) + x = 2 between the values of 1 and 2 returning the answer of x = 1.370 to the default tolerance of three decimal places.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM