VBA Array



  • VBA Array
    di Raffaele_53 (utente non iscritto) data: 12/10/2013 13:28:37

    Salve,
    Sto cercando di capire come fuzionano gli Array.
    Domanda da imbranato. Volessi trovare una combinazione tra dei numeri.

    Sub Sheet_Fill_Array()
    Dim myarray As Variant
    myarray = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    End Sub

    Potrei fare un ciclo For, partendo da myarray = Array(1) e finire sino all'ultimo?
    Ho già provato, mi sembra che creando un ciclo For, compongo la stringa mà questo sarebbe testo racchiuso tra " ".

    Sub Sheet_Fill_Array()
    Dim myarray As Variant
    Dim test As String
    URiga = Range("A" & Rows.Count).End(xlUp).Row
    For x = 1 To URiga
    test = test & " " & Cells(x, 1) & ","
    Next
    NomeVar = Left(test, Len(test) - 1)
    [c1] = NomeVar
    myarray = Array(NomeVar)
    aaa = WorksheetFunction.Sum(myarray)
    MsgBox (aaa)
    End Sub

    Grazie mille



  • di Grograman data: 14/10/2013 08:46:43

    Sai che non ho capito la domanda?

    Un solo appunto, ricorda che se non diversamente specificato (option base 1 in testa al modulo) gli array e le matrici partono da base 0.
    Quindi nel tuo esempio:


     
    Funzionante:
    Sub Sheet_Fill_Array() 
    Dim myarray As Variant 
    dim i as long 
    myarray = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 
    for i = 0 to 9
    debug.print myarray(i)
    next i 
    End Sub 
    
    Errata:
    Option Explicit
    
    Sub Sheet_Fill_Array()
      Dim myarray As Variant
      Dim i As Long
      
      myarray = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
      For i = 1 To 10
        Debug.Print myarray(i)
      Next i
      
    End Sub
    
    
    Ri-Funzionante:
    Option Explicit
    Option Base 1
    
    Sub Sheet_Fill_Array()
      Dim myarray As Variant
      Dim i As Long
      
      myarray = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
      For i = 1 To 10
        Debug.Print myarray(i)
      Next i
      
    End Sub



  • di Raffaele_53 (utente non iscritto) data: 14/10/2013 17:23:25

    Ciao, in effetti ho fatto un brutto esempio.
    Non mi serve realmente, volevo lavorarci sù per capirlo meglio.

    In realta, tutti gli esempi fatti in rete sulle (combinazioni di somme) sono fatti con cicli Next e scrittura dei dati sul foglio.

    Pensavo, mà con gli Array, non si dovrebbero velocizzare le macro?

    Ora se posso scrivere un Array in questo modo:
    myarray = Array(Cells(1, 2), Cells(2, 2), Cells(3, 2), Cells(4, 2), Cells(5, 2), Cells(6, 2), Cells(7, 2), Cells(8, 2), Cells(9, 2), Cells(10, 2))

    Creare un Next, all'interno di un Array.

    A) Ci fosse solo un valore metterei:
    For Y = 1 to 1000
    myarray = Array(Cells(Y, 2))
    Somma = WorksheetFunction.Sum(myarray)
    'MsgBox (Somma)
    If Somma = "il richiesto" Then
    Cellaxy = Somma
    end if
    Next Y

    B) Fosse due valore metterei:
    For Y = 1 to 1000
    For X = 1 to 1000
    myarray = Array(Cells(Y, 2),Cells(X, 2))
    Somma = WorksheetFunction.Sum(myarray)
    'MsgBox (Somma)
    If Somma = "il richiesto" Then
    Cellaxy = Somma
    end if
    Next X
    Next Y

    Ps. Non conosco come passare dalla fine del ciclo A a quello B?
    PPs. Secondo la Tua opinione snellisco o appesantisco il tutto?



  • di gaetanopr data: 14/10/2013 20:33:23

    cit>>Ora se posso scrivere un Array in questo modo:
    myarray = Array(Cells(1, 2), Cells(2, 2), Cells(3, 2), Cells(4, 2), Cells(5, 2), Cells(6, 2), Cells(7, 2), Cells(8, 2), Cells(9, 2), Cells(10, 2))

    Ciao Raffaele, in questo modo hai usato la funzione Array assegnando alla matrice myarray i valori elencati tra parentesi, partendo da indice zero fino a indice 9
    Se invece vuoi usare un ciclo, devi fare diversamente
    esempio A con matrice unidimensionale, dove la matrice viene riempita con i valori presenti da B1 a B10
    esempio B con matrice bidimensionale dove la matrice viene riempita con i valori presenti da A1:A10(1^ dimensione) e B1:B10(2^dimensione)
    Ricordati che gli array vanno sempre dichiarati a differenza delle normali variabili

     
    Sub A()
    
    Dim myarray(0 To 9)
    
    For Y = 0 To 9
    myarray(Y) = Cells(Y + 1, 2)
    'Somma = WorksheetFunction.Sum(myarray)
    'If Somma = "il richiesto" Then
    'Cellaxy = Somma
    'End If
    Next Y
    End Sub
    
    Sub B()
    Dim myarray(1 To 10, 1 To 2)
    For Y = 1 To 2
    For X = 1 To 10
    myarray(X, Y) = Cells(X, Y)
    'Somma = WorksheetFunction.Sum(myarray)
    'MsgBox (Somma)
    'If Somma = "il richiesto" Then
    'Cellaxy = Somma
    'End If
    Next X
    Next Y
    
    End Sub



  • di Vecchio Frac data: 15/10/2013 10:30:24

    A completamento e integrazione, aggiungo la mia ^_^

    cit. "Ora se posso scrivere un Array in questo modo:
    myarray = Array(Cells(1, 2), Cells(2, 2), Cells(3, 2), Cells(4, 2), Cells(5, 2), Cells(6, 2), Cells(7, 2), Cells(8, 2), Cells(9, 2), Cells(10, 2)) "
    --> Poichè ti riferisci a un range ben preciso, puoi assegnarlo direttamente a una variabile in questo modo (il range in questione è B2:B10):
    Set v = [b1:b10]
    e poi ottenere la somma dei suoi elementi così:
    per range a una colonna:
    somma=Application.Sum(v)
    per range a due colonne:
    somma=Application.Sum(v.columns(1))







  • di Raffaele_53 (utente non iscritto) data: 15/10/2013 13:23:52

    Comunque grazie delle spiegazioni date sinora.
    Ci riprovo, insicuro nello spiegare. Se metto:

    Sub calcola()
    Dim myarray As Variant
    For x = 1 To 1000
    myarray = WorksheetFunction.Sum(Array(x))
    If myarray = 500 Then
    MsgBox "trovato"
    End If
    Next
    End Sub

    Alla 500esima operazione, mi risponde Trovato, ma se invece di 500 avessi messo 1005 non può trovarlo.

    Intendevo come si potrebbe fare per digli che se non lo trova, di aggiungere un secondo numero nel Array(?). In teoria usando due numeri, ex 1000+5 oppure Ex 999+6 mi dovrà sempre rispondere Trovato.



  • di Raffaele_53 (utente non iscritto) data: 15/10/2013 13:29:55

    Oppure cosa dovrei scrivere per domandargli quali sono i numeri da 1 a 10 che danno come risulatato 23?
    Come già detto facendo dei cicli for su questi dieci numeri.

    Una strada con l'uso dell' Array esiste?



  • di Vecchio Frac data: 15/10/2013 13:41:39

    Difficilmente troverai un uso dell'istruzione Array nel modo che hai descritto poco fa :)
    E' interessante il problema generico che hai indicato nell'ultimo post.
    Sì, dei cicli for sull'insieme per verificare se la somma degli elementi dà un certo risultato.
    L'algoritmo di risoluzione è indipendente dai contenitori utilizzati (vettori, matrici su foglio, collection, ecc.) per conservare le variabili.
    Quindi dire "una strada con l'uso degli array" è inapplicabile al contesto perchè questi sono solo i contenitori dei dati.






  • di gaetanopr data: 15/10/2013 13:50:23

    Anch'io concordo sul dire che la risoluzione è indipendente dall'uso degli array per la raccolta dei vari elementi da utilizzare per il calcolo stesso
    Cercando in rete ho trovato una funzione che potrebbe interessarti, nella routine Combinazioni basta cambiare i valori nella'Array N usando anche un ciclo for, poi bisogna agire su somma desiderata e su K che stabilisce con quanti elementi combinati si deve arrivare alla somma desiderata
     
    Public Function SommeCombinazioniSemplici(ByVal arrayElementi As Variant, _
                                              ByVal dimensioneGruppo As Integer, _
                                              ByVal sommaTest As Integer) As Collection
      
        Dim sommaTemp As Integer
        Dim LC As New Collection
        If UBound(arrayElementi) = 0 Then Set SommeCombinazioniSemplici = LC
        If dimensioneGruppo = 0 Or dimensioneGruppo > UBound(arrayElementi) Then Set SommeCombinazioniSemplici = LC
        Dim aP() As Integer
        ReDim aP(dimensioneGruppo - 1)
        Dim i As Integer
        For i = 0 To UBound(aP)
            aP(i) = i
        Next i
        Dim j As Integer
        Dim C As String
        Dim cnt As Integer
        Do
            C = ""
            sommaTemp = 0
            For i = 0 To UBound(aP)
                C = C & "[" & arrayElementi(aP(i)) & "]"
                sommaTemp = sommaTemp + arrayElementi(aP(i))
            Next i
            If sommaTemp = sommaTest Then LC.Add (C)
      
            cnt = 0
            For i = UBound(aP) To 0 Step -1
                If aP(i) = UBound(arrayElementi) - cnt Then
                    cnt = cnt + 1
                    If cnt = UBound(aP) + 1 Then Exit Do
                Else
                    aP(i) = aP(i) + 1
                    For j = 0 To UBound(aP)
                        If i < j Then aP(j) = aP(i) + (j - i)
                    Next
                    Exit For
                End If
            Next i
        Loop
      
        Set SommeCombinazioniSemplici = LC
      
    End Function
    
    
    
    Sub Combinazioni()
    Dim N() As Variant
        N = Array(5, 1, 23, 7, 10, 2, 8, 15, 20, 4, 30)
        Dim sommaDesiderata As Integer
        sommaDesiderata = 30
        
        Dim K As Byte
        K = 3
      
        Dim Comb As Collection
        Set Comb = SommeCombinazioniSemplici(N, K, sommaDesiderata)
      
        'Test
        Dim s As String
        Dim i As Integer
        For i = 1 To Comb.Count
            s = s & (Comb(i)) & vbCrLf
        Next i
        MsgBox s
    End Sub
    



  • di Vecchio Frac data: 15/10/2013 13:52:06

    Vedo (googlando) che questo argomento ricorre anche recentemente in Rete ^_^
    Sarebbe davvero "lustruoso" trovare una soluzione generica adattabile a tutti i casi (non soltanto trovare le coppie di numeri che danno un determinato risultato, ma trovare gli n numeri che danno un certa somma all'interno di una lista determinata di numeri).






  • di Vecchio Frac data: 15/10/2013 13:52:53

    (mentre scrivevo mi sono perso l'intervento di gaetano)





  • di Vecchio Frac data: 15/10/2013 13:55:22

    Caspita mi pare che funzioni bene ^_^
    Migliorabile, d'accordo, ma efficace... me lo sto studiando :)





  • di Raffaele_53 (utente non iscritto) data: 15/10/2013 18:22:12

    Beato Te che la capisci/leggi la Function

    Comunque intendevo dire "se con un numero non riesco, usane due per trovare. Non riesci usane tre ecc ecc sino alla fine dei dieci numeri"---> sempre riferito all'Array
    Sicuro d'aver scritto una stronzata.



  • di Raffaele_53 (utente non iscritto) data: 15/10/2013 18:39:24

    Vi allego un files calcolato come "Binario", di altro forum e autore Jorel

    Non riesco metterci mani, secondo me si ferma alla prima combinazione trovata e non prosegue a trovare altre combinazioni.

    Bello sarebbe che trova la corrispondenza, la segna in ex cella K1
    Continua e se trova altre la mette in K2

    Rimane il fatto che sino a dieci numeri e veloce, provate a metterne 30/50?

    Ps L'ultimo numero nella colonna A, sarebbe il risultato che vogliamo ottenere.
    Grazie mille, era solo per velocizzare eventuali macro.



  • di gaetanopr (utente non iscritto) data: 15/10/2013 19:03:36

    cit>>Bello sarebbe che trova la corrispondenza, la segna in ex cella K1
    Continua e se trova altre la mette in K2
    Ciao raffaele ancora non l'ho studiato bene(sempre se riuscirò a capirlo del tutto)il file, però questo non credo sia un problema effettuarlo, anche la questione di iniziare con un numero e proseguire 2,3,4 fin quanto non trova le condizioni, credo che basta incrementare K da macro(partendo da 2 incrementando se non trova combinazioni) infine per velocizzare la macro si potrebbe fare in modo che ad esempio se la somma desiderata è 100 e abbiamo valori che arrivano a 1000 è inutile includerli tutti in quanto sappiamo già a priori che dal 100esimo in poi non ci servono.



  • di Raffaele_53 (utente non iscritto) data: 15/10/2013 19:23:00

    Ciao gaetanopr
    Giusta osservazione, ordinando in crescente la colonna A (tranne l'ultimo), otteniamo che invece di fare un ciclo for per tutte le celle (limitiamo i valori solo agli uguali o inferiori)
    Però di norma la cifra finale è sempre più alta anche dell'ultimo valore.
    Non Vi voglio stressare, era solo un mio pensiero.
    Nel frattempo, credo d'aver capito Array



  • di Raffaele_53 (utente non iscritto) data: 17/10/2013 20:13:54

    Ciao a tutti, grazie gaetanopr (molto bello).

    Ho due (MIEI) problemi (ho settato un Array fisso di 20 numeri in A1:A20 scritti dal 1 al 20):
    Ci fossero meno di 20 combinazioni, il mio codice è errato, fossero di più sarebbe errato lo stesso.
    Attualmente la somma sarà di trenta
    Attualmente ho inserito un'inputbox che mi chiede su quanti addendi deve operare?
    Finche usa Tot addendi, funziona bene e veloce. Anche con altri valori d'addendi.
    Fare un ciclo for da 1 a 20 addendi diventa pesante.

    Una domanda se possibili?
    A) Possibile creare l'array in base a quanti addendi si vogliono usare e farlo lavorare per tutte le celle della colonna A
    (attualmente come scritto lavora solo su 20 numeri)

    Spero d'essermi fatto capire.

    Ps. Usando il codice con questo esempio, ho notato che digitando 7 nell'inputbox, For K = Quanti To Quanti + 1 esegue dal 7 al 8. Però se notate la colonna F rimane Vuota, che significa che non esistono più valori uguali dopo 8 addendi.
    Interpretazione mia giusta?

    Pps. Usando numeri con virgola non funziona bene (forse al posto di interger devo mettere double?)

    Ppps. Altra domanda che se non supero la lomanda A, non serve a nulla.
     
    Sub Combinazioni()
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    Columns("E:XFD").ClearContents
    URiga = Range("A" & Rows.Count).End(xlUp).Row
    C = 5
    Dim N() As Variant
        N = Array([A1], [A2], [A3], [A4], [A5], [A6], [A7], [A8], [A9], [A10], [A11], [A12], [A13], [A14], [A15], [A16], [A17], [A18], [A19], [A20])
        Dim sommaDesiderata As Integer
        'sommaDesiderata = InputBox("Digitare la somma da ricercare", , 0)
        'If sommaDesiderata = 0 Then Exit Sub
        ''''''
        sommaDesiderata = 30
        ''''''
        Dim Quanti As Integer
        Quanti = InputBox("La procedura sarebbe lunga, inserisci un numero di quanti potrebbero essere gli addendi?", , 0)
        If Quanti = 0 Then Exit Sub
        
        Dim K As Byte
        'For K = 2 To 4
        For K = Quanti To Quanti + 1
        
        
        Dim Comb As Collection
        Set Comb = SommeCombinazioniSemplici(N, K, sommaDesiderata)
           
        For i = 1 To Comb.Count
        Cells(i, C) = (Comb(i))
        Next i
        C = C + 1
        Next
        Application.Calculation = xlCalculationAutomatic
        Application.ScreenUpdating = True
       MsgBox "Ho Terminato"
    
    End Sub