This code is (slightly) adapted from Tushar Mehta's original:
Sub test()
ComboSum 211.01, 100, Range("B1:B30")
End Sub
Sub ComboSum(dTgt As Double, MaxSoln As Integer, rInp As Range)
' from http://www.tushar-mehta.com/excel/templates/match_values/index.html
' Lists the cells in single-column range rInp that total dTgt
' MaxSoln is the number of solutions wanted. Specify zero for all.
' Solutions are listed in the column to the right of rInp
Const dEps As Double = 0.00000001
Const sSep As String = ", "
Dim asSoln() As String ' solutions
Dim vInp() As Variant ' values in rInp
Dim daBeg As Date ' start time
Dim WF As WorksheetFunction
If rInp.Columns.Count <> 1 Then Exit Sub
Set WF = Application.WorksheetFunction
daBeg = Now()
' get the values from the range
vInp = WF.Transpose(WF.Transpose(WF.Transpose(rInp.Value)))
ReDim asSoln(0 To 0)
RecursiveMatch MaxSoln, dTgt, vInp(), LBound(vInp), 0, dEps, asSoln, "", sSep
' list the solutions
asSoln(UBound(asSoln)) = "Done @ " & Format(Now(), "hh:mm:ss")
rInp.Offset(, 1).Resize(UBound(asSoln) + 1, 1).Value = WF.Transpose(asSoln)
End Sub
Sub RecursiveMatch(ByVal MaxSoln As Integer, _
ByVal dTgt As Double, _
ByRef vInp() As Variant, _
ByVal iCurrInx As Integer, _
ByVal dCurrTot As Double, _
ByVal dEps As Double, _
ByRef asSoln() As String, _
ByVal sSoln As String, _
ByVal sSep As String)
Dim i As Integer
For i = iCurrInx To UBound(vInp)
If Abs(dCurrTot + vInp(i) - dTgt) <= dEps Then
asSoln(UBound(asSoln)) = dCurrTot + vInp(i) _
& sSep & Format(Now(), "hh:mm:ss") _
& sSoln & sSep & CStr(i)
If UBound(asSoln) Mod 100 = 0 Then Debug.Print UBound(asSoln) + 1 & " solutions ..."
If MaxSoln <> 0 Then If UBound(asSoln) >= MaxSoln Then Exit Sub
ReDim Preserve asSoln(UBound(asSoln) + 1)
ElseIf dCurrTot + vInp(i) < dTgt - dEps And iCurrInx < UBound(vInp) Then
RecursiveMatch MaxSoln, dTgt, vInp(), i + 1, _
dCurrTot + vInp(i), dEps, asSoln(), _
sSoln & sSep & CStr(i), sSep
If MaxSoln <> 0 Then If UBound(asSoln) >= MaxSoln Then Exit Sub
End If
Next i
End Sub
Bookmarks