-2

I need to sum a set of values and arrive at another value, this set of values can vary (meaning that it can contain 4 or 20 values), but I only need one combination that uses the values without modifying any of them and reach the correct final value.

Example:

Amounts:
435.97
40180.6
261.19
14861.68
108.7
77.97
316.02
1345.4
1255.96
10851.02
3517.04

Value to reach using combination of the amounts above: 57050.23

This topic shows how to do something very alike in several languages, but I need it in PowerShell or a formula that does that on Excel.

Community
  • 1
  • 1
  • 3
    So, what constitutes a "correct final value"? Apparently it's not the sum of all input values. And what have you tried so far? SO is not a place where you define your requirements and other people write code for you. – Ansgar Wiechers Jul 29 '15 at 20:49
  • Correct final value is the amount I want to reach at the end, in this case: 57050.23. You don't need to sum all values, only one combination that can reach that value would suffice. I don't have anything coded, I was trying to find a formula on Excel that can reach the correct value like a Permutation or something like it, but couldn't find it yet. As soon as I code something I'll post it here, sorry – Graci Robert Jul 29 '15 at 20:56
  • http://www.handyexcelmacros.net/handy_excel_macros_003.htm – Tim Williams Jul 29 '15 at 20:59
  • Can you add each value multiple times or can you use each value only once to reach the desired amount? – nbayly Jul 29 '15 at 21:11
  • each value only once, no repeating or changing values – Graci Robert Jul 29 '15 at 21:18
  • My non-VBA solution here; http://excelxor.com/2014/09/15/which-numbers-add-up-to-total/ has a theoretical limit of 20 input values (though in practice tends to struggle at that level), so you may wish to try that. However, beyond that limit VBA will be your only option. There is a more refined, follow-up post as well: http://excelxor.com/2015/02/10/which-numbers-add-up-to-total-2-multiple-solutions/ though this does not appear to be appropriate to your situation. – XOR LX Jul 29 '15 at 21:22

1 Answers1

0

We manage to call an Excel macro through powershell and it is working. It's a pretty extensive code (815 lines) but here is the part we call the vba macro and put the result on a vector to filter the value (orders, in this case) that match the value we want to reach:

$WorksheetAutomation12.Activate()
$ExcelAutomation.Run("Descobrir")

$WorksheetAutomation12.Columns.Item('D').NumberFormat = "0"

$AuxMacro = $CNPJCount+5

$FilterOrdersMacro = @()

for($i=6;$i -le $AuxMacro;$i++)
{
    $MacroValue = $WorksheetAutomation12.Cells.Item($i, 4).value()
    if(($MacroValue -ne 0) -and ($MacroValue -ne $null))
    {
        $FilterOrdersMacro += , "$MacroValue"
    }
}

$FilterOrdersMacro

and the VBA macro:

Option Explicit

Dim dv() As Double
Dim dvTeste() As String

Dim dMeta As Double

Dim e As Long
Dim eTeste As Long

Dim blAchou As Boolean

Dim vOrigem()
Dim vOrigemTeste()

Dim rLast As Long
Dim blParar
Dim dDiferença As Double

Sub Descobrir()

        With ThisWorkbook.Sheets("Macro")
            'rLast is the last used row:
            rLast = .Cells(.Rows.Count, "A").End(xlUp).Row

            'Put column A into a vector:
            vOrigem = Application.Transpose(.Range("A1:A" & rLast))
            vOrigemTeste = Application.Transpose(.Range("B1:B" & rLast))


            '"Meta" is the value we want to reach
            dMeta = .Range("C2")

            .Range("C5:C" & rLast + 4).ClearContents
            .Range("E2:F2").ClearContents
            .Range("E4") = "Executing . . ."

            Recursar

            .Range("E4").ClearContents

            'Throw the solution on the worksheet
            If blAchou Then
'                DisporResultado

            Else
                If blParar Then

                Else

                End If
            End If
        End With

End Sub

Sub DisporResultado()
    With ThisWorkbook.Sheets("Macro")
        Dim n As Long
        Dim nTeste As Long

        .Range("C5:C" & rLast + 5).ClearContents
        .Range("D5:D" & rLast + 5).ClearContents
        .Range("E2") = Soma(dv)

        .Range("F2") = dDiferença

        For n = 1 To UBound(dv)
            .Cells(n + 5, "C") = dv(n)
        Next n

        For nTeste = 1 To UBound(dvTeste)
            .Cells(nTeste + 5, "D") = dvTeste(nTeste) '
        Next nTeste


    End With
End Sub

Function Recursar(Optional r0 As Long)

    Dim r As Long
    Dim n As Long

    Dim rTeste As Long
    Dim nTeste As Long

    Dim dSoma As Double

   If r0 = 0 Then

        e = 0
        eTeste = 0

        r0 = 1
        blAchou = False
        blParar = False

        dDiferença = 1.79769313486231E+308
    End If

    DoEvents

    For r = r0 To rLast
        e = e + 1
        eTeste = eTeste + 1

        ReDim Preserve dv(1 To e)
        ReDim Preserve dvTeste(1 To eTeste)

        dv(e) = vOrigem(r)
        dvTeste(eTeste) = vOrigemTeste(r)

        If Abs(dSoma - dMeta) < Abs(dDiferença) Then
            dDiferença = dSoma - dMeta
            DisporResultado
        End If
        Select Case dSoma
            Case Is < dMeta
                If r = rLast Then
                    e = e - 2
                    eTeste = eTeste - 2
                    If e > 0 Then
                        ReDim Preserve dv(1 To e)
                        ReDim Preserve dvTeste(1 To eTeste)
                    End If
                Else
                    Recursar r + 1
                End If
            Case Is > dMeta
                e = e - 1
                eTeste = eTeste - 1
                If e > 0 Then
                    ReDim Preserve dv(1 To e)
                    ReDim Preserve dvTeste(1 To eTeste)
                End If
                If r = rLast Then
                    e = e - 1
                    eTeste = eTeste - 1
                    If e > 0 Then
                        ReDim Preserve dv(1 To e)
                        ReDim Preserve dvTeste(1 To eTeste)
                    End If
                End If
            Case dMeta
                blAchou = True
        End Select
        If blAchou found Or blParar Then Exit Function
    Next r

End Function

Function Soma(v As Variant) As Double

    Dim n As Long
    Dim dSoma As Double
    For n = 1 To UBound(v)
        dSoma = dSoma + v(n)
    Next n
    Soma = dSoma
End Function

Sub Parar()
    blParar = True
End Sub

captions: Parar = Stop. Soma = sum. Achou = value found.
thanks for all your help :)