Mrrrr's Forum (VIEW ONLY)
Un forum care ofera solutii pentru unele probleme legate in general de PC. Pe langa solutii, aici puteti gasi si alte lucruri interesante // A forum that offers solutions to some PC related issues. Besides these, here you can find more interesting stuff.
Lista Forumurilor Pe Tematici
Mrrrr's Forum (VIEW ONLY) | Reguli | Inregistrare | Login

POZE MRRRR'S FORUM (VIEW ONLY)

Nu sunteti logat.
Nou pe simpatie:
Dulceata_ta36
Femeie
25 ani
Galati
cauta Barbat
28 - 53 ani
Mrrrr's Forum (VIEW ONLY) / Tutoriale si Ghiduri Utile // Tutorials and useful guides / [EXCEL] VBA Solver - Find Combinations of Numbers that Sum to Total Moderat de TRaP, TonyTzu
Autor
Mesaj Pagini: 1
TRaP
Moderator

Inregistrat: acum 7 ani
Postari: 863
I needed a VBA solver similar to the Solver add-in in Excel, but that works faster and with decimals. Solver tends to find numbers close to the total I need, and I didn't spend time to configure it very much to give me exact results.

Anyway, below is a VBA macro built with ChatGPT that found the desired number combination in 1 second (or less).

This solver does the following:
✅ automatic deletion of old “Combinations” sheet (if exists from previous calculation)
✅ range of numbers to combine and total required value input via InputBoxes
✅ formatted output (headings, alignment)
✅ the requested total shown at the top
✅ per-combination totals displayed and verified
✅ highlighting of cells in the original range that form part of any found combination

Later edit by Mrrrr:
✅ prompts for the error margin (tolerance) via an InputBox (e.g. “0,1” → ±0,1 range)
✅ added a Yes/No prompt to choose between exact match or within margin
✅ if user selects Exact match, it uses margin = 0,001 for precision
✅ if user selects With margin, asks for the numeric margin
✅ if margin = 0, it finds all possible combinations (no filtering)
✅ if margin ≠ 0, it stops after 30 combinations and shows a message to refine margin to get less combinations


Sub VBA_Solver()
    Dim wsComb As Worksheet
    Dim wsSource As Worksheet
    Dim rng As Range
    Dim cell As Range
    Dim numbers() As Double
    Dim target As Double
    Dim margin As Double
    Dim n As Long, i As Long, j As Long
    Dim resultCount As Long
    Dim combo() As Long
    Dim currentSum As Double
    Dim colOffset As Long
    Dim combinationTotalRow As Long
    Dim searchMode As VbMsgBoxResult
    Dim stopSearch As Boolean
   
    '--- Ask for range
    On Error Resume Next
    Set rng = Application.InputBox("Select the range of numbers:", "Select Range", Type:=8)
    If rng Is Nothing Then Exit Sub
    On Error GoTo 0

    '--- Ask for target total
    target = Application.InputBox("Enter the target total:", "Target Total", Type:=1)
    If target = 0 And StrPtr(target) = 0 Then Exit Sub

    '--- Ask whether to use margin
    searchMode = MsgBox("Do you want to use an error margin (± tolerance)?", vbYesNo + vbQuestion, "Search Mode")
   
    If searchMode = vbYes Then
        margin = Application.InputBox("Enter allowed error margin (e.g., 0.1 for ±0.1):", "Error Margin", Type:=1)
        If margin < 0 Then margin = Abs(margin)
    Else
        margin = 0.001 ' small tolerance for floating point precision
    End If

    Set wsSource = rng.Worksheet

    '--- Delete old "Combinations" sheet if it exists
    Application.DisplayAlerts = False
    On Error Resume Next
    ThisWorkbook.Worksheets("Combinations").Delete
    On Error GoTo 0
    Application.DisplayAlerts = True

    '--- Create new sheet
    Set wsComb = ThisWorkbook.Worksheets.Add
    wsComb.Name = "Combinations"

    '--- Store numbers into array
    n = rng.Count
    ReDim numbers(1 To n)
    i = 1
    For Each cell In rng
        numbers(i) = cell.Value
        i = i + 1
    Next cell

    '--- Write source numbers in column A
    wsComb.Cells(1, 1).Value = "Source Range: " & rng.Address(External:=True)
    wsComb.Cells(2, 1).Value = "Requested Total:"
    wsComb.Cells(2, 2).Value = target
    wsComb.Cells(3, 1).Value = "Allowed Error Margin (±):"
    wsComb.Cells(3, 2).Value = IIf(searchMode = vbYes, margin, "Exact match")
    wsComb.Cells(5, 1).Value = "Numbers"
    For i = 1 To n
        wsComb.Cells(i + 5, 1).Value = numbers(i)
    Next i

    '--- Prepare search
    resultCount = 0
    combinationTotalRow = n + 7
    colOffset = 2
    stopSearch = False

    '--- Search for combinations (bitmask)
    For i = 1 To (2 ^ n) - 1
        ReDim combo(1 To n)
        currentSum = 0
        For j = 1 To n
            If (i And (2 ^ (j - 1))) <> 0 Then
                currentSum = currentSum + numbers(j)
                combo(j) = 1
            End If
        Next j

        '--- Evaluate combination
        If margin = 0 Then
            ' Margin = 0 ? show all combinations
            resultCount = resultCount + 1
        ElseIf Abs(currentSum - target) <= margin Then
            resultCount = resultCount + 1
        End If

        '--- Save combination if it meets criteria
        If (margin = 0) Or (Abs(currentSum - target) <= margin) Then
            wsComb.Cells(5, colOffset + resultCount - 1).Value = "Combination " & resultCount

            For j = 1 To n
                If combo(j) = 1 Then
                    wsComb.Cells(j + 5, colOffset + resultCount - 1).Value = numbers(j)
                    ' Highlight source range cells
                    rng.Cells(j).Interior.Color = RGB(255, 255, 150)
                End If
            Next j

            wsComb.Cells(combinationTotalRow, colOffset + resultCount - 1).Formula = _
                "=SUM(" & wsComb.Range(wsComb.Cells(6, colOffset + resultCount - 1), _
                wsComb.Cells(5 + n, colOffset + resultCount - 1)).Address(False, False) & ")"
        End If

        '--- Stop after 30 if margin ? 0
        If margin <> 0 And resultCount >= 30 Then
            stopSearch = True
            Exit For
        End If
    Next i

    '--- Formatting
    With wsComb
        .Cells(5, 1).Font.Bold = True
        .Rows(5).Font.Bold = True
        .Rows(5).HorizontalAlignment = xlCenter
        .Columns("A:" & Chr(64 + colOffset + resultCount)).AutoFit
        .Cells(combinationTotalRow, 1).Value = "Total per combination:"
        .Cells(combinationTotalRow, 1).Font.Bold = True
    End With

    '--- Messages
    If margin = 0 Then
        MsgBox resultCount & " total combination(s) listed (margin = 0 ? all shown).", vbInformation
    ElseIf stopSearch Then
        MsgBox "More than 30 combinations found. Please refine your error margin." & vbCrLf & _
                "If you want all combinations, click Yes and add margin: 0", vbExclamation
    Else
        MsgBox resultCount & " combination(s) found within ±" & margin & " of target " & target, vbInformation
    End If
End Sub


Source:
ChatGPT


pus acum 2 saptamani
   
Pagini: 1  

Mergi la